How to manage Linux containers with Ansible Container

We love containers and use this technology every day. However, containers aren’t perfect. However, over the past few months, a number of projects have emerged that address some of the problems we have experienced.

We started using containers with Docker because this project made this technology so popular. Besides using a container, we learned how to use docker-compose and started to manage their projects. Our productivity skyrocketed!

After a while, we started to notice problems. The most obvious of these are related to the container imaging process. The Docker tool uses a custom file format as a recipe for building container images – Dockerfiles. This format is easy to learn and in a short time you are ready to create your own container images. Problems arise if you want to master better skills or have complex scripts.

Let’s take a break and head to another country: the world of Ansible. Do you know what this is? It’s great, isn’t it? You do not have? Well, it’s time to learn something new. Ansible is a project that allows you to manage your infrastructure by recording tasks and executing them in environments of your choice. No need to install and configure any services; everything can work easily from your laptop. Many people are already embracing Ansible.

Imagine this scenario: you’ve invested in Ansible, you’ve written many incredible roles and schemas that you use to manage your infrastructure, and you’re thinking about investing in containers. What should you do? Start writing container image definitions with shell scripts and Dockerfiles? It doesn’t sound like that.

Several people on the Ansible development team asked this question and realized that the same roles and schemas that people write and use on a daily basis can also be used to create container images. Not only that – they can be used to manage the entire lifecycle of container projects. The Ansible Container project was born from these ideas. It leverages existing Ansible roles that can be turned into container images and can even be used for the entire application lifecycle, from build to production deployment.

Let’s talk about the issues we mentioned regarding best practices in the context of Dockerfiles. Warning: this will be very specific and technical. Here are the three main questions we have:

1. Shell scripts embedded in Dockerfiles.

When writing Dockerfiles, you can specify a script that will be interpreted via / bin / sh -c … It could be something like this:

RUN dnf install -y nginx

where RUN is the Dockerfile command and the rest are its arguments (which are passed to the shell). But imagine a more complex scenario:

RUN set -eux; 

this "case" statement is generated via ""

wget -O go.tgz "$url"; 
echo "${goRelSha256} *go.tgz" | sha256sum -c -; 

This is taken from the official golang image. It doesn’t look pretty, does it?

2. You can’t easily parse Dockerfiles.

Dockerfiles are a new format with no formal specification. This is tricky if you need to handle Dockerfiles in your infrastructure (for example, automate the build process a bit). The only spec is the code that is part dockerd… The problem is that you cannot use it as a library. The simplest solution is to write a parser yourself and hope for the best. Isn’t it better to use some well-known markup language like YAML or JSON?

3. Difficult to control.

If you are familiar with the inner images of containers, you may know that each image is composed of layers. After creating the container, the layers are stacked on top of each other (for example, like pancakes) using the union file system technology. The problem is that you cannot explicitly control this layering – you cannot say, “A new layer begins here.” You are forced to modify your Dockerfile in such a way as to impair readability. The big problem is that you need to use a set of best practices to achieve optimal results – it is very difficult for beginners here.

Comparing Ansible language and Dockerfiles

The biggest disadvantage of Dockerfiles over Ansible is that Ansible is much more powerful as a language. For example, Dockerfiles has no direct knowledge of variables, whereas Ansible has a complete templating system (variables are just one of its functions). Ansible contains a large number of modules that can be easily used, for example wait_forwhich can be used to check if a service is ready, for example, wait for a service to be ready before continuing. With Dockerfiles, this is all shell script. Therefore, if you need to find out when ready to go, you need to do it using the shell (or install it separately). Another problem with shell scripting is that maintenance becomes cumbersome with increasing complexity. A lot of people have already figured this out and turned these scripts into Ansible.