Editor's note: This article covers utilizing the Ansible docker_image module for working with containers. But if you're using a different container toolchain, you may have other options. Be sure to check out our full collection of container articles for the latest and greatest tools for managing Linux containers.
Building container images and placing them into upstream repositories is a common way of making your images available to the outside world. However, you might encounter scenarios where you don't want to upload a container image to a repository. Maybe you don't want to upload your image for security reasons, or maybe your cluster is just sufficiently small (e.g., in your home lab) that you don't want to deal with a repository (whether external or self-hosted).
If you have a use case for avoiding the storage of your container images in a repository, then you're in luck! The Ansible docker_image module makes it easy to build, save, and load your images without ever hitting a repository. This article walks you through some simple playbooks that you can incorporate into your workflow to manage containers with Ansible.
Environment overview
First, let me introduce the basic directory structure that I’ll be using for this tutorial:
$ ls -lah
total 28K
drwxr-xr-x 2 acritelli acritelli 4.0K May 6 11:24 ./
drwxr-xr-x 29 acritelli acritelli 4.0K May 3 08:26 ../
-rw-rw-r-- 1 acritelli acritelli 261 May 2 22:23 save.yml
-rw-rw-r-- 1 acritelli acritelli 254 May 2 22:20 build.yml
-rw-rw-r-- 1 acritelli acritelli 49 May 2 22:01 Dockerfile
-rw-rw-r-- 1 acritelli acritelli 54 May 2 22:45 inventory.ini
-rw-rw-r-- 1 acritelli acritelli 403 May 2 22:49 load.yml
I have a Dockerfile, an Ansible inventory, and a few simple playbooks for working with the Ansible Docker image module. The hosts in this environment are defined in the inventory.ini
file:
$ cat inventory.ini
[build_host]
docker-build.example.com
[docker_hosts]
docker01.example.com
docker02.example.com
There are three hosts that I am working with in this article:
- docker-build - This server is used to build Docker containers. The container images are then saved off this host.
- docker01 and docker02 - These hosts are used to run containers. Containers from build01 are uploaded and made available to both of these hosts.
All three hosts in the environment have Docker and the Docker SDK for Python installed. The SDK is a requirement for using the Ansible Docker modules. You can install all of these from the standard repositories via yum
:
[root@docker-build ~]# yum install docker python-docker-py
Building a container
The first step in this workflow is building an actual container image. The image that I use in this article is very simple: it just launches a netcat
listener on port 8080 and waits for client connections, as you can see from the Dockerfile:
$ cat Dockerfile
FROM alpine:latest
EXPOSE 8080
CMD nc -l -p 8080
A simple Ansible playbook can then be used to build a container image based on this Dockerfile:
$ cat build.yml
---
- hosts: build_host
gather_facts: no
tasks:
- name: create build directory
file:
path: /root/demo-dockerfile
state: directory
owner: root
group: root
mode: '0755'
- name: copy Dockerfile
copy:
src: ./Dockerfile
dest: /root/demo-dockerfile/Dockerfile
owner: root
group: root
mode: '0644'
- name: build container image
docker_image:
name: democontainer:v1.0
build:
path: /root/demo-dockerfile
source: build
state: present
This playbook creates a build directory on the "build" server, copies the Dockerfile to this directory, and then builds the container using the docker_image
Ansible module. The source parameter set to "build" tells the module to build a container image based on the listed path. In this case, the path points to the directory and Dockerfile that were copied to the build host.
Running this playbook successfully builds the container image:
$ ansible-playbook -i inventory.ini build.yml
PLAY [build_host] ****************************************************************************************************************************************************************************
TASK [create build directory] ****************************************************************************************************************************************************************
changed: [docker-build.example.com]
TASK [copy Dockerfile] ***********************************************************************************************************************************************************************
changed: [docker-build.example.com]
TASK [build container image] *****************************************************************************************************************************************************************
changed: [docker-build.example.com]
PLAY RECAP ***********************************************************************************************************************************************************************************
docker-build.example.com : ok=3 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
You can log into the build server after the playbook completes to see that the democontainer:v1.0
image has been successfully built and is available to launch a container:
[root@docker-build ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
democontainer v1.0 f2d7d737743e About a minute ago 5.61 MB
docker.io/alpine latest f70734b6a266 13 days ago 5.61 MB
Saving a container image
Container images can be saved to a tarball using the docker save
command. Tarballs provide a convenient way to "export" your container images. The Ansible Docker image module also includes support to export an image to a tar
file:
$ cat save.yml
---
- hosts: build_host
gather_facts: no
tasks:
- name: archive container image as a tarball
docker_image:
name: democontainer:v1.0
archive_path: /root/democontainer_v1_0.tar
source: pull
state: present
- name: fetch archived image
fetch:
src: /root/democontainer_v1_0.tar
dest: ./democontainer_v1_0.tar
flat: true
This playbook first archives the image using the docker_image
module and then fetches the file from the remote server and places it into the local directory. After successfully running the playbook, you have a tar
file in your local directory that contains the contents of the image:
$ ansible-playbook -i inventory.ini save.yml
PLAY [build_host] ****************************************************************************************************************************************************************************
TASK [archive container image as a tarball] **************************************************************************************************************************************************
changed: [docker-build.example.com]
TASK [fetch archived image] ******************************************************************************************************************************************************************
changed: [docker-build.example.com]
PLAY RECAP ***********************************************************************************************************************************************************************************
docker-build.example.com : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Notice that the democontainer
is now tarred up in the local directory:
$ ls
ansible.cfg save.yml build.yml democontainer_v1_0.tar Dockerfile inventory.ini load.yml
Loading a container image
With the image now downloaded to your local system, you can again use the Ansible Docker image module to upload the tarball to all of your Docker hosts and import it. Once imported, the container image is available to launch containers.
$ cat load.yml
---
- hosts: docker_hosts
gather_facts: no
tasks:
- name: copy tarball to host
copy:
src: ./democontainer_v1_0.tar
dest: /root/democontainer_v1_0.tar
- name: load container from tarball
docker_image:
name: democontainer:v1.0
load_path: /root/democontainer_v1_0.tar
state: present
source: load
This playbook copies the tarball created in the save.yml
playbook to all of the Docker hosts. It then loads the container image to make it available to future docker run
commands.
$ ansible-playbook -i inventory.ini load.yml
PLAY [docker_hosts] **************************************************************************************************************************************************************************
TASK [copy tarball to host] ******************************************************************************************************************************************************************
changed: [docker01.example.com]
changed: [docker02.example.com]
TASK [load container from tarball] ***********************************************************************************************************************************************************
changed: [docker01.example.com]
changed: [docker02.example.com]
PLAY RECAP ***********************************************************************************************************************************************************************************
docker01.example.com : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
docker02.example.com : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Once the playbook has successfully run, the container image can be seen when listing out the available images on any of the Docker hosts:
[root@docker01 ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
democontainer v1.0 f2d7d737743e 25 hours ago 5.61 MB
[root@docker02 ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
democontainer v1.0 f2d7d737743e 25 hours ago 5.61 MB
You can then launch a container on one of the hosts and see that it works.
Launch the container:
[root@docker01 ~]# docker run --rm -it -p 8080:8080 democontainer:v1.0
The below command is executed in a separate session:
[root@docker01 ~]# telnet localhost 8080
Trying ::1...
Connected to localhost.
Escape character is '^]'.
hello!
You can see that the output is echoed back within the container via netcat
:
[root@docker01 ~]# docker run --rm -it -p 8080:8080 democontainer:v1.0
hello!
If you want to avoid the need to copy the container image to your local host and then copy it back to the Docker hosts, you can check out the Ansible synchronize module. While out of scope for this article, you can gain some efficiencies with this thin wrapper around rsync
.
Wrapping up
This article walked you through the use of the Ansible Docker image module, which provides a way to manage container images on remote hosts. You learned how to build, save, and load an image through simple Ansible playbooks. While using a container repository is a standard way to make an image available across multiple hosts, the use of this Ansible module can also provide a simple mechanism for sharing your images in a small environment.
[ Need more on Ansible? Take a free technical overview course from Red Hat. Ansible Essentials: Simplicity in Automation Technical Overview. ]
Sobre el autor
Anthony Critelli is a Linux systems engineer with interests in automation, containerization, tracing, and performance. He started his professional career as a network engineer and eventually made the switch to the Linux systems side of IT. He holds a B.S. and an M.S. from the Rochester Institute of Technology.
Navegar por canal
Automatización
Las últimas novedades en la automatización de la TI para los equipos, la tecnología y los entornos
Inteligencia artificial
Descubra las actualizaciones en las plataformas que permiten a los clientes ejecutar cargas de trabajo de inteligecia artificial en cualquier lugar
Nube híbrida abierta
Vea como construimos un futuro flexible con la nube híbrida
Seguridad
Vea las últimas novedades sobre cómo reducimos los riesgos en entornos y tecnologías
Edge computing
Conozca las actualizaciones en las plataformas que simplifican las operaciones en el edge
Infraestructura
Vea las últimas novedades sobre la plataforma Linux empresarial líder en el mundo
Aplicaciones
Conozca nuestras soluciones para abordar los desafíos más complejos de las aplicaciones
Programas originales
Vea historias divertidas de creadores y líderes en tecnología empresarial
Productos
- Red Hat Enterprise Linux
- Red Hat OpenShift
- Red Hat Ansible Automation Platform
- Servicios de nube
- Ver todos los productos
Herramientas
- Training y Certificación
- Mi cuenta
- Soporte al cliente
- Recursos para desarrolladores
- Busque un partner
- Red Hat Ecosystem Catalog
- Calculador de valor Red Hat
- Documentación
Realice pruebas, compras y ventas
Comunicarse
- Comuníquese con la oficina de ventas
- Comuníquese con el servicio al cliente
- Comuníquese con Red Hat Training
- Redes sociales
Acerca de Red Hat
Somos el proveedor líder a nivel mundial de soluciones empresariales de código abierto, incluyendo Linux, cloud, contenedores y Kubernetes. Ofrecemos soluciones reforzadas, las cuales permiten que las empresas trabajen en distintas plataformas y entornos con facilidad, desde el centro de datos principal hasta el extremo de la red.
Seleccionar idioma
Red Hat legal and privacy links
- Acerca de Red Hat
- Oportunidades de empleo
- Eventos
- Sedes
- Póngase en contacto con Red Hat
- Blog de Red Hat
- Diversidad, igualdad e inclusión
- Cool Stuff Store
- Red Hat Summit