Executando um comando Ansible em vários contêineres docker

Preciso executar um comando em vários contêineres em execução. Por exemplo, digamos que meu aplicativo precise executar uma atualização da estrutura de dados em um banco de dados depois de receber atualizações de código. Para fazer isso, queremos correr docker build <project_dir> -t latest, entao docker stop; docker rm; docker run. Nesta fase, podemos assumir que atualizamos o código principal do contêiner, mas ainda precisamos executar essa atualização do banco de dados usando as próprias ferramentas do aplicativo.

Essencialmente, preciso de alguma maneira de obter uma lista de contêineres em execução, filtrada por alguns critérios e registrar esses IDs de contêiner com Ansible. Então, para cada contêiner, executamos o comando.

Comer:

- name: Get list of running containers  docker:      image: my-image:latest      state: running      register: container_ids

Esta tarefa armazenaria a lista de contêineres em execução que usam my-image:latest para container_ids. Então executamos o comando:

- name: Exec the database update  cmd: "docker exec -it {{ item }} my-app-db-update.sh"  with: container_ids

Como realmente não queremos usar contêineres ativos para esse tipo de operação, uma opção melhor seria iniciar um novo contêiner de uso único agindo nos mesmos dados:

- 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

O acima é apenas pseudo-código - ele não será executado. Como faço para realizar a tarefa de armazenar uma lista de contêineres do docker em execução que atendem a certos critérios, para que eu possa aplicar um comando a cada contêiner na lista usando qualquer um docker exec ou docker run?

Há surpreendentemente pouco sobre isso online.

Dado o seguinte exemplo de saída de docker ps:

$ docker psCONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES7e21761c9c44        busybox             "top"                    22 minutes ago      Up 22 minutes                           agitated_yonath7091d9c7cc56        nginx               "nginx -g 'daemon off"   23 minutes ago      Up 23 minutes       80/tcp, 443/tcp     fervent_blackwell

Este manual lhe dará uma idéia de como capturar os dados que você precisa e como executar ações iterando na lista fornecida. É um exemplo muito simples, e você terá que adaptá-lo às suas necessidades. Isso é de propósito:

---- 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

As partes interessantes são:

  1. Reúna a lista de contêineres em um determinado host (localhost no meu exemplo).Eu usei uma planície shell invocação para poder usar awk para filtrar a saída. O resultado é armazenado em um registro. Como a entrada é uma lista, isso terá uma consequência direta sobre como recuperar os dados de volta, mais abaixo. Descomentar o debug tarefa entre comparar os dados armazenados no registro com e sem uma lista.

  2. Iterar sobre os resultados do registro (ID do contêiner) e usar o docker_container módulo para executar uma ação (command parametro). Você pode usar links e volumes_from em seu docker_container invocacao. Verifique a documentação on-line do modulo para os detalhes.

@ thrig, isso precisa ser aplicado a contêineres em execução no sistema one, não em vários. Se eu precisasse aplicar o comando a vários sistemas, simplesmente usaria um inventário para fazer isso.

@ techraf – eu editei a pergunta. Agora inclui um ponto de interrogação.

Então você está realmente pedindo uma sintaxe de um pipe semelhante a ’ docker ps / grep my-image: latest | cut-f 1`?

Não @techraf, é mais eficiente usar o docker ps – filter nessa instância. A questão é sobre idempotency e best-practice, uma vez que executar o acima como comandos shell não é idempotent. Você teria pensado que faria mais sentido usar a própria API docker do ansible para fazer isso, se possível.

O que a idempotência tem a ver com a consulta? Duvida. Explicar.

Idempotência é um conceito importante com ansible, @ techraf. Ao executar comandos shell ingenuamente usando o ansible, perdemos a capacidade de avaliar se o sistema atendeu aos requisitos do manual (e pular a tarefa) ou não. É por isso que é sempre aconselhável executar módulos de API nativos ansible em vez de shell. O manual ansible afirma, wrt para stdout_lines, para não usá-lo frequentemente nesta conta.