Introduction
Ansible Bender is a tool that gives the ability to creates containers using Ansible playbooks and turns them into container images. Ansible-bender relies on Ansible connection plugins (buildah) for performing builds.
Features
- You can build your container images with buildah as a backend.
- Ansible playbook is your build recipe.
- You are able to set various image metadata via CLI or as specific Ansible vars:
- working directory
- environment variables
- labels
- user
- default command
- exposed ports
- volume mounts during the build
Why should you care?
- Ansible can take care of your container images
- Using Ansible to define an image instead of a bash script
- You can recycle your playbooks and roles
- Ansible playbooks are YAML and easy to maintain
Requirements
I’m using Fedora 34 for this setup, if you are using another distro, please have a look at install documentation.
Podman
Podman is a tool for managing containers and images, volumes mounted into those containers, and pods made from groups of containers.
$ dnf install podman
Buildah
Buildah - a tool that facilitates building Open Container Initiative (OCI) container images. more details: https://opencontainers.org/
$ dnf install buildah
Installing Ansible Bender
Option 1. Easy way - stable version delivered by the distribution (good for production environment)
$ dnf install ansible-bender
Option 2. Setup using python pip (latest versions)
$ python3 -m virtualenv .env
$ .env/bin/pip install --upgrade pip
$ .env/bin/pip install ansible selinux ansible-bender
$ source .env/bin/activate
If you prefer to not use virtualenv, just install by running
pip install
command.
In my case, I will take the option 2, because I would like to try out the latest version.
Let’s try out
In this example, I’ll create a simple image with azcopy (Azure Storage data transfer utility) tooling installed.
1. Lets create a playbook.yml file
---
- hosts: all
vars:
ansible_bender:
base_image: "docker.io/library/python:3-alpine"
target_image:
name: "docker.io/emedeiros/azcopy:{{ azcopy_version }}"
labels:
version: "{{ azcopy_version }}"
cmd: "{{ azcopy_bin_path }}/azcopy"
azcopy_pkg_url: https://azcopyvnext.azureedge.net/release20210415/azcopy_linux_amd64_10.10.0.tar.gz
azcopy_bin_path: /usr/local/bin
azcopy_version: 10.10.0
tasks:
- name: Install utils
package:
name: "{{ item }}"
state: present
loop:
- unzip
- tar
- libc6-compat
- name: "Install azcopy package"
unarchive:
remote_src: true
src: "{{ azcopy_pkg_url }}"
dest: "{{ azcopy_bin_path }}"
extra_opts: [--strip-components=1]
- name: Register current version installed
command: "{{ azcopy_bin_path }}/azcopy --version"
register: "version"
- name: Check installation
fail:
msg: "azcopy {{ azcopy_version }} installation failure"
when: version.stdout.find(azcopy_version) == -1
- name: Display version installed
debug:
msg: "{{ version.stdout_lines }}"
2. Build a container image on top of that.
ansible-bender build ./playbook.yml --no-cache
PLAY [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont] ***********
TASK [Gathering Facts] *********************************************************
ok: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont]
TASK [Install utils] ***********************************************************
changed: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont] => (item=unzip)
changed: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont] => (item=tar)
changed: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont] => (item=libc6-compat)
TASK [Install azcopy 10.10.0 package] ******************************************
changed: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont]
TASK [Register current version installed] **************************************
changed: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont]
TASK [Check installation] ******************************************************
skipping: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont]
TASK [Display version installed] ***********************************************
ok: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont] => {
"msg": [
"azcopy version 10.10.0"
]
}
PLAY RECAP *********************************************************************
docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont : ok=5 changed=3 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Getting image source signatures
Copying blob sha256:b2d5eeeaba3a22b9b8aa97261957974a6bd65274ebd43e1d81d0a7b8b752b116
Copying blob sha256:ff362123de14f499ce9b7bb1907ff5955b1938f615a28e197b1481421c5c73e7
Copying blob sha256:cf9eca8251cd62ceb3a229ca035194b95a08a4dc365b39f9ef7ebf642ded304b
Copying blob sha256:20b112836d68cd0ab33d97dba32b52802b47033c5010fff39c1e900ee296d3c1
Copying blob sha256:dcdc49916e794252075ff5dd1f365e201b54c0184914a7e72378654a8d728b29
Copying blob sha256:092fe46bf30114b055a176ba559eeebbc16d7749824a260fbe73eb2168981dad
Copying config sha256:73155863de9e6907f0daa82ea28f87963847e9cb0794377a0e462a952622a9b1
Writing manifest to image destination
Storing signatures
73155863de9e6907f0daa82ea28f87963847e9cb0794377a0e462a952622a9b1
Image 'docker.io/emedeiros/azcopy:10.10.0' was built successfully \o/
3. Check the logs
$ ansible-bender list-builds
$ ansible-bender get-logs [ID]
PLAY [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont] ***********
TASK [Gathering Facts] *********************************************************
ok: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont]
TASK [Install utils] ***********************************************************
changed: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont] => (item=unzip)
changed: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont] => (item=tar)
changed: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont] => (item=libc6-compat)
TASK [Install azcopy 10.10.0 package] ******************************************
changed: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont]
TASK [Register current version installed] **************************************
changed: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont]
TASK [Check installation] ******************************************************
skipping: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont]
TASK [Display version installed] ***********************************************
ok: [docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont] => {
"msg": [
"azcopy version 10.10.0"
]
}
PLAY RECAP *********************************************************************
docker-io-emedeiros-azcopy-10-10-0-20210505-124806108269-cont : ok=5 changed=3 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
4. Inspecting the image
$ ansible-bender inspect
ansible_extra_args: null
base_image: docker.io/library/python:3-alpine
build_container: docker-io-emedeiros-azcopy-10-10-0-20210504-004735245186-cont
build_finished_time: 20210504-004802331000
build_id: '54'
build_start_time: 20210504-004738906160
build_user: null
build_volumes: []
buildah_from_extra_args: null
builder_name: buildah
cache_tasks: false
debug: false
final_layer_id: f9d6847614df9cc52d0363e47036678a391b423cea0adf086758020048f7c2a6
layering: true
layers:
- base_image_id: null
cached: true
content: null
layer_id: 81fc860d6a56caaca274cfca7731c5b6a70462aa4a682bae01fac1c8b755915f
- base_image_id: 81fc860d6a56caaca274cfca7731c5b6a70462aa4a682bae01fac1c8b755915f
cached: false
content: 231c2edbda7f1dc0873ddb80e2cd01bca729a6daf16858688c3a8cdd3c0c30aa2d62a9f82a0842431c160fa5e618b7441db3251ef1ae5dc20e3ec8b3b511a6e0
layer_id: sha256:c2375d7e2a61a414eae19a44e4f104f6f8ad8553d4e455b2b2eb74ae7b02f22d
- base_image_id: sha256:c2375d7e2a61a414eae19a44e4f104f6f8ad8553d4e455b2b2eb74ae7b02f22d
cached: false
content: 231c2edbda7f1dc0873ddb80e2cd01bca729a6daf16858688c3a8cdd3c0c30aa2d62a9f82a0842431c160fa5e618b7441db3251ef1ae5dc20e3ec8b3b511a6e0
layer_id: sha256:745661e4a80aeaae998490b4e35338e2b7e012c1df00da6cb4b25cc2356cbb72
- base_image_id: sha256:745661e4a80aeaae998490b4e35338e2b7e012c1df00da6cb4b25cc2356cbb72
cached: false
content: 231c2edbda7f1dc0873ddb80e2cd01bca729a6daf16858688c3a8cdd3c0c30aa2d62a9f82a0842431c160fa5e618b7441db3251ef1ae5dc20e3ec8b3b511a6e0
layer_id: sha256:a7e8af07e7b26140b7899dd75c2b1eb4bbd3f8be5516d97e5e0ee5ccefa869dc
- base_image_id: sha256:a7e8af07e7b26140b7899dd75c2b1eb4bbd3f8be5516d97e5e0ee5ccefa869dc
cached: false
content: 231c2edbda7f1dc0873ddb80e2cd01bca729a6daf16858688c3a8cdd3c0c30aa2d62a9f82a0842431c160fa5e618b7441db3251ef1ae5dc20e3ec8b3b511a6e0
layer_id: sha256:a2c8876b1a89a37118b9fde9c21109e274e0c32186a9245a0a7170e0c8fcbb7c
- base_image_id: sha256:a2c8876b1a89a37118b9fde9c21109e274e0c32186a9245a0a7170e0c8fcbb7c
cached: false
content: 1614e2ee75928f45566e53ef469c231015ea35658c7eced751a936d08188f17e763d7c3698d0836e40a7ba9d5f2bd989637b7c83bd9da6db6b110809c6d964f2
layer_id: sha256:20638d7872905e67c89bb16a089927c95f4a8122fceab33a89c4bef399db0f40
- base_image_id: sha256:20638d7872905e67c89bb16a089927c95f4a8122fceab33a89c4bef399db0f40
cached: false
content: fb0262070dba94482b9af356d55d87005019009007a7ac89c7c9067875c055284dadfe7aba37a0d6bc7b5848fd1767a1c294f2bfe33768a27dac1929fc188862
layer_id: sha256:39e77550d3b2035b807cbbb682b41f2a9298c80ac669301439d32f599f57624d
- base_image_id: sha256:39e77550d3b2035b807cbbb682b41f2a9298c80ac669301439d32f599f57624d
cached: false
content: 430e9e45296402e1efa2330bcdf58adfa24faabdd3e7be6b3e30e604dbebbc840f149693e129619db196d4673234bf67512d93d27e19aade3e8ac26db6107a8e
layer_id: sha256:a095cfc4562fafdb4ff321fcc826f362ae123a6e46ee39de3d0396c91ce883fd
metadata:
annotations: {}
cmd: /usr/local/bin/azcopy
entrypoint: null
env_vars: {}
labels:
version: 10.10.0
ports: []
user: null
volumes: []
working_dir: null
playbook_path: ./playbook.yml
pulled: false
python_interpreter: null
squash: false
state: done
target_image: docker.io/emedeiros/azcopy:10.10.0
verbose: false
verbose_layer_names: null
5. Testing the image
$ podman run emedeiros/azcopy:10.10.0
output expected:
docker run emedeiros/azcopy:10.10.0
AzCopy 10.10.0
Project URL: github.com/Azure/azure-storage-azcopy
AzCopy is a command line tool that moves data into and out of Azure Storage.
To report issues or to learn more about the tool, go to github.com/Azure/azure-storage-azcopy
The general format of the commands is: 'azcopy [command] [arguments] --[flag-name]=[flag-value]'.
Usage:
azcopy [command]
...
6. Push your image to your repo (optional)
$ podman login docker.io
Login Succeeded!
$ podman push docker.io/emedeiros/azcopy:10.10.0
Bonus
Why not ansible-roles?
ansible-galaxy role install eduardolmedeiros.azcopy -p roles
playbook sample:
---
- hosts: all
vars:
ansible_bender:
base_image: "docker.io/library/centos:8"
target_image:
name: "docker.io/emedeiros/azcopy"
- name: import role azcopy
include_role:
name: eduardolmedeiros.azcopy
That’s all folks. Cheers.