Running an Ansible command in multiple docker containers
Given the following example output from docker ps
:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7e21761c9c44 busybox "top" 22 minutes ago Up 22 minutes agitated_yonath
7091d9c7cc56 nginx "nginx -g 'daemon off" 23 minutes ago Up 23 minutes 80/tcp, 443/tcp fervent_blackwell
This playbook will give you an idea of how to capture the data you need and how to run actions iterating on the provided list. It's a very simple example, and you'll have to adapt it to your needs. That's on purpose:
---
- hosts: localhost
gather_facts: no
tasks:
- name: gather list of containers
shell: docker ps | awk '/{{ item }}/{print $1}'
register: list_of_containers
with_items:
- busybox
#- name: debug
# debug: msg="{{ list_of_containers }}"
- name: run action in container(s)
docker_container:
name: temp-container
image: busybox
command: uptime
cleanup: yes
detach: yes
register: result_of_action
with_items:
- list_of_containers.results.stdout_lines
The interesting parts are:
Gather the list of containers in a given host (
localhost
in my example). I've used a plainshell
invocation to be able to useawk
to filter out the output. The result is stored in a register. Since the input is a list, this will have a direct consequence on how to retrieve the data back, more below. Uncomment thedebug
task in between to compare the data stored in the register with and without a list.Iterate over the register's results (container ID) and use the
docker_container
module to run an action (command
parameter). You can uselinks
andvolumes_from
in yourdocker_container
invocation. Check the on-line documentation of the module for the details.
Related videos on Youtube
DMCoding
Updated on September 18, 2022Comments
-
DMCoding over 1 year
I need to run a command against multiple running containers. For example, let's say my app needs to run a data structure update against a database after receiving code updates. To do this, we want to run
docker build <project_dir> -t latest
, thendocker stop; docker rm; docker run
. At this stage we can assume we have updated the container's core code, but we still need to run that database update using the app's own tooling.Essentially, I need some way to get a list of running containers, filtered by some criteria, and register those container IDs with Ansible. Then for each container we run the command.
Like this:
- name: Get list of running containers docker: image: my-image:latest state: running register: container_ids
This task would store the list of running containers which use
my-image:latest
tocontainer_ids
. Then we exec the command:- name: Exec the database update cmd: "docker exec -it {{ item }} my-app-db-update.sh" with: container_ids
Since we don't really want to use active containers for this type of operation, a better option would be to start a new single-use container acting on the same data instead:
- name: Run the database update cmd: "docker run --rm --volumes-from {{ item }} --link:mydb:db my-app sh -c 'my-app-db-update.sh'" with: container_ids
The above is only pseudo-code -- it won't actually run. How do I accomplish the task of storing a list of running docker containers which meet certain criteria, so that I can then apply a command to each container in the list using either
docker exec
ordocker run
?There's surprisingly little about this online.
-
DMCoding over 7 years@thrig, this needs to be applied to containers running on one system, not multiple ones. If I needed to apply the command to multiple systems I would simply use an inventory to accomplish that.
-
DMCoding over 7 years@techraf -- I've edited the question. It now includes a question mark.
-
DMCoding over 7 yearsNo @techraf, it's more efficient to use docker ps --filter in that instance. The question is about idempotency and best-practice, since running the above as shell commands is not idempotent. You'd have thought it would make more sense to use ansible's own docker API to accomplish this, if able.
-
techraf over 7 yearsWhat does idempotency have to do with query? Any query. Please explain.
-
DMCoding over 7 yearsIdempotency is an important concept with ansible, @techraf. When running shell commands naively using ansible, we lose the ability to assess whether the system has met the playbook's requirements (and skip the task) or not. That's why it is always advisable to run ansible native API modules instead of shell. The ansible manual states, wrt to stdout_lines, not to use it often on this account.
-