Назад | Перейти на главную страницу

Запуск команды Ansible в нескольких контейнерах докеров

Мне нужно запустить команду для нескольких запущенных контейнеров. Например, предположим, что моему приложению необходимо выполнить обновление структуры данных для базы данных после получения обновлений кода. Для этого мы хотим запустить docker build <project_dir> -t latest, затем docker stop; docker rm; docker run. На этом этапе мы можем предположить, что обновили основной код контейнера, но нам все еще нужно запустить это обновление базы данных, используя собственные инструменты приложения.

По сути, мне нужен способ получить список запущенных контейнеров, отфильтрованный по некоторым критериям, и зарегистрировать эти идентификаторы контейнеров в Ansible. Затем для каждого контейнера запускаем команду.

Как это:

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

Эта задача будет хранить список запущенных контейнеров, которые используют my-image:latest к container_ids. Затем выполняем команду:

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

Поскольку на самом деле мы не хотим использовать активные контейнеры для этого типа операций, лучшим вариантом было бы запустить новый одноразовый контейнер, работающий с теми же данными:

- 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

Это всего лишь псевдокод - на самом деле он не будет работать. Как мне выполнить задачу по хранению списка запущенных контейнеров докеров, которые соответствуют определенным критериям, чтобы затем я мог применить команду к каждому контейнеру в списке, используя либо docker exec или docker run?

В Интернете об этом на удивление мало.

Учитывая следующий пример вывода из 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

Эта инструкция даст вам представление о том, как собирать необходимые данные и как выполнять действия, повторяющиеся в предоставленном списке. Это очень простой пример, и вам придется адаптировать его к вашим потребностям. Это специально:

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

Интересные части:

  1. Соберите список контейнеров на данном хосте (localhost в моем примере). Я использовал простой shell вызов, чтобы иметь возможность использовать awk чтобы отфильтровать вывод. Результат сохраняется в регистре. Поскольку входные данные представляют собой список, это будет иметь прямое влияние на то, как получить данные обратно, подробнее ниже. Раскомментируйте debug промежуточная задача - сравнить данные, хранящиеся в регистре, со списком и без него.

  2. Перебирайте результаты реестра (идентификатор контейнера) и используйте docker_container модуль для запуска действия (command параметр). Ты можешь использовать links и volumes_from в твоем docker_container призыв. Проверьте онлайн-документацию модуль для подробностей.