5

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, then docker 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 to container_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 or docker run?

There's surprisingly little about this online.

6
  • @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
    Dec 4, 2016 at 15:53
  • @techraf -- I've edited the question. It now includes a question mark.
    – DMCoding
    Dec 4, 2016 at 15:56
  • So you are actually asking for a syntax of a pipe similar to docker ps | grep my-image: latest | cut -f 1?
    – techraf
    Dec 5, 2016 at 4:25
  • No @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.
    – DMCoding
    Dec 6, 2016 at 10:10
  • What does idempotency have to do with query? Any query. Please explain.
    – techraf
    Dec 6, 2016 at 10:13

1 Answer 1

6

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:

  1. Gather the list of containers in a given host (localhost in my example). I've used a plain shell invocation to be able to use awk 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 the debug task in between to compare the data stored in the register with and without a list.

  2. Iterate over the register's results (container ID) and use the docker_container module to run an action (command parameter). You can use links and volumes_from in your docker_container invocation. Check the on-line documentation of the module for the details.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .