Building container images with the ansible-bender tool

Learn how to use Ansible to execute commands in a container.
Register or Login to like
3 mistakes to avoid when learning to code in Python

Containers and Ansible blend together so nicely—from management and orchestration to provisioning and building. In this article, we'll focus on the building part.

If you are familiar with Ansible, you know that you can write a series of tasks, and the ansible-playbook command will execute them for you. Did you know that you can also execute such commands in a container environment and get the same result as if you'd written a Dockerfile and run podman build.

Here is an example:

- name: Serve our file using httpd
  hosts: all
  - name: Install httpd
      name: httpd
      state: installed
  - name: Copy our file to httpd’s webroot
      src: our-file.txt
      dest: /var/www/html/

You could execute this playbook locally on your web server or in a container, and it would work—as long as you remember to create the our-file.txt file first.

But something is missing. You need to start (and configure) httpd in order for your file to be served. This is a difference between container builds and infrastructure provisioning: When building an image, you just prepare the content; running the container is a different task. On the other hand, you can attach metadata to the container image that tells the command to run by default.

Here's where a tool would help. How about trying ansible-bender?

$ ansible-bender build the-playbook.yaml fedora:30 our-httpd

This script uses the ansible-bender tool to execute the playbook against a Fedora 30 container image and names the resulting container image our-httpd.

But when you run that container, it won't start httpd because it doesn't know how to do it. You can fix this by adding some metadata to the playbook:

- name: Serve our file using httpd
  hosts: all
      base_image: fedora:30
        name: our-httpd
        cmd: httpd -DFOREGROUND
  - name: Install httpd
      name: httpd
      state: installed
  - name: Listen on all network interfaces. 
      path: /etc/httpd/conf/httpd.conf  
      regexp: '^Listen ' 
      line: Listen   
  - name: Copy our file to httpd’s webroot
      src: our-file.txt
      dest: /var/www/html

Now you can build the image (from here on, please run all the commands as root—currently, Buildah and Podman won't create dedicated networks for rootless containers):

# ansible-bender build the-playbook.yaml
PLAY [Serve our file using httpd] ****************************************************
TASK [Gathering Facts] ***************************************************************    
ok: [our-httpd-20191004-131941266141-cont]

TASK [Install httpd] *****************************************************************
loaded from cache: 'f053578ed2d47581307e9ba3f64f4b4da945579a082c6f99bd797635e62befd0'
skipping: [our-httpd-20191004-131941266141-cont]

TASK [Listen on all network interfaces.] *********************************************
changed: [our-httpd-20191004-131941266141-cont]

TASK [Copy our file to httpd’s webroot] **********************************************
changed: [our-httpd-20191004-131941266141-cont]

PLAY RECAP ***************************************************************************
our-httpd-20191004-131941266141-cont : ok=3    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0 

Getting image source signatures
Copying blob sha256:4650c04b851c62897e9c02c6041a0e3127f8253fafa3a09642552a8e77c044c8
Copying blob sha256:87b740bba596291af8e9d6d91e30a01d5eba9dd815b55895b8705a2acc3a825e
Copying blob sha256:82c21252bd87532e93e77498e3767ac2617aa9e578e32e4de09e87156b9189a0
Copying config sha256:44c6dc6dda1afe28892400c825de1c987c4641fd44fa5919a44cf0a94f58949f
Writing manifest to image destination
Storing signatures 
Image 'our-httpd' was built successfully \o/

The image is built, and it's time to run the container:

# podman run our-httpd
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using Set the 'ServerName' directive globally to suppress this message

Is your file being served? First, find out the IP of your container:

# podman inspect -f '{{ .NetworkSettings.IPAddress }}' 7418570ba5a0

And now you can check:

$ curl
Ansible is ❤

What were the contents of your file?

This was just an introduction to building container images with Ansible. If you want to learn more about what ansible-bender can do, please check it out on GitHub. Happy building!

What to read next
Engineer. Hacker. Speaker. Tinker. Red Hatter. Likes containers, linux, open source, python 3, rust, zsh, tmux.


Hi Tomas, thank you for sharing. I didn't know Ansible could be used to build containers and run commands inside. It definitely looks promising. Keep up the good work.

Hey there, I’m Taylor. I’m a professional web developer and trainer worked in Microtek Learning Inc. in Canada. I am a fan of web development, technology, and programming. I’m also interested in education and entrepreneurship.

I just want you to know that I’m deeply grateful for your amazing post!

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.