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:
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?
$ 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:
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.
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.
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.
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.