Docker-Compose. Как Дождаться Готовности Контейнера

Введение Есть много статей о запуске контейнеров и написании docker-compose.yml .

Но долгое время для меня оставался неясным вопрос, как правильно поступить, если контейнер не должен запускаться до тех пор, пока другой контейнер не будет готов к обработке его запросов или не выполнит определенный объем работы.

Этот вопрос стал актуальным после того, как мы начали активно использовать docker-compose , вместо запуска отдельных докеров.

Зачем это нужно? Действительно, пусть приложение в контейнере Б зависит от готовности сервиса в контейнере А.

И при запуске приложение в контейнере Б не получает этот сервис.

Что оно должно делать? Вариант второй:

  • первый - умереть (желательно с кодом ошибки)
  • второй — подождать, а потом все равно умереть, если приложение в контейнере B не ответило в течение отведенного таймаута
После того, как контейнер B умер, docker-compose (конечно, в зависимости от настроек) перезапустит его, и приложение в контейнере B снова попытается связаться с сервисом в контейнере A. Это будет продолжаться до тех пор, пока сервис в контейнере А не будет готов отвечать на запросы, или пока мы не заметим, что наш контейнер постоянно перегружен.

И на самом деле это нормальный путь для многоконтейнерной архитектуры.

Но, в частности, мы столкнулись с ситуацией, когда контейнер А запускается и готовит данные для контейнера Б.

Приложение в контейнере Б не знает, как проверить, готовы данные или нет; он сразу начинает с ним работать.

Поэтому нам приходится самим получать и обрабатывать сигнал о готовности данных.

Я думаю, что можно привести еще несколько вариантов использования.

Но самое главное, вам нужно точно понимать, зачем вы это делаете.

В противном случае лучше использовать стандартные инструменты.

docker-compose Немного идеологии Если внимательно прочитать документацию, там все написано.

А именно - каждый Контейнер является независимой единицей и должен сам обеспечивать, чтобы все сервисы, включая ему доступны.

Поэтому вопрос не в том, запускать или не запускать контейнер, а в том, стоит ли внутри контейнера проверьте готовность всех необходимых сервисов и только после этого передаем управление приложению-контейнеру.

Как это реализовано В решении этой проблемы мне очень помогло описание docker-compose , Здесь этот Часть этого И статья , рассказывая о правильном использовании входная точка И cmd .

Итак, что нам нужно получить:

  • есть приложение А, которое мы завернули в контейнер А
  • он запускается и начинает отвечать ОК на порту 8000
  • а также есть приложение Б, которое мы запускаем из контейнера Б, но оно должно начать работать не раньше, чем приложение А начнет отвечать на запросы на порту 8000
Официальная документация предлагает два способа решения этой проблемы.

Первый — написать свой собственный входная точка в контейнере, который выполнит все проверки и затем запустит рабочее приложение.

Второй — использовать уже написанный командный файл подожди-for-it.sh .

Мы попробовали оба пути.



Написание собственной точки входа

Что случилось входная точка ? Это просто исполняемый файл, который вы указываете при создании контейнера в Докерфайл в поле ВХОДНАЯ ТОЧКА .

Этот файл, как уже говорилось, выполняет проверки, а затем запускает основное приложение-контейнер.

Итак, что мы получаем: Давайте создадим папку Входная точка .

В нем есть две подпапки - контейнер_А И контейнер_B .

В них мы будем создавать наши контейнеры.

Для контейнера A возьмем простой http-сервер на Python. После запуска он начинает отвечать на запросы на порт 8000. Чтобы сделать наш эксперимент более наглядным, мы установим задержку в 15 секунд перед запуском сервера.

Оказывается следующее docker-файл для контейнера A :

  
  
  
  
   

FROM python:3 EXPOSE 8000 CMD sleep 15 && python3 -m http.server --cgi

Для контейнера B мы создадим следующее docker-файл для контейнера B :

FROM ubuntu:18.04 RUN apt-get update RUN apt-get install -y curl COPY .

/entrypoint.sh /usr/bin/entrypoint.sh ENTRYPOINT [ "entrypoint.sh" ] CMD ["echo", "!!!!!!!! Container_A is available now !!!!!!!!"]

И в эту же папку поместим наш исполняемый файл enterpoint.sh. у нас будет так

#!/bin/bash set -e host="conteiner_a" port="8000" cmd="$@" >&2 echo "!!!!!!!! Check conteiner_a for available !!!!!!!!" until curl http://"$host":"$port "; do >&2 echo "Conteiner_A is unavailable - sleeping" sleep 1 done >&2 echo "Conteiner_A is up - executing command" exec $cmd

Что происходит в контейнере B:

  • Когда он запускается, он работает ВХОДНАЯ ТОЧКА , т. е.

    запускает точка входа.

    sh

  • точка входа.

    sh , используя завиток , начинает опрашивать порт 8000 контейнера A. Он делает это до тех пор, пока не получит ответ 200 (т.е.

    завиток в этом случае он закончится нулевым результатом и цикл завершится)

  • При получении 200 цикл завершается и управление передается команде, указанной в переменной $cmd .

    И показывает то, что мы указали в докер-файле в поле КМД , т.е.

    echo "!!! Контейнер_A доступен!!!!!!!!" .

    Почему это так, описано выше.

    статья

  • Мы печатаем - !!! Контейнер_А доступен!!! и мы заканчиваем.

Мы запустим все с помощью docker-compose .

docker-compose.yml у нас есть вот этот:

version: '3' networks: waiting_for_conteiner: services: conteiner_a: build: .

/conteiner_A container_name: conteiner_a image: conteiner_a restart: unless-stopped networks: - waiting_for_conteiner ports: - 8000:8000 conteiner_b: build: .

/conteiner_B container_name: conteiner_b image: waiting_for_conteiner.entrypoint.conteiner_b restart: "no" networks: - waiting_for_conteiner

Здесь, в контейнер_а не обязательно указывать порты: 8000:8000 .

Это сделано для того, чтобы иметь возможность проверить работу работающего в нем http-сервера извне.

Кроме того, контейнер B не подлежит перезапуску после завершения работы.

Запустим:

docker-compose up —-build

Видим, что секунд 15 появляется сообщение о недоступности контейнера А, а затем Теги: #*nix #Системное администрирование #docker-compose

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.