Как заставить Docker Compose ждать контейнеров зависимостей
Хотя этого не всегда достаточно. Некоторые из ваших контейнеров могут иметь зависимости друг от друга, которые нарушают работу приложения, если они не могут быть выполнены. В этом руководстве мы покажем, как настроить службы Compose для учета этих зависимостей, что позволит запускать контейнеры по порядку.
Основы
Docker Compose поддерживает поле depends_on
в файлах docker.compose.yml
. Службы могут включать имена своих братьев и сестер в depends_on
. Это предотвращает запуск контейнера до тех пор, пока не будут запущены зависимые службы.
services: api: image: example.com/api:latest depends_on: - db web-app: image: example.com/web-app:latest depends_on: - api db: image: mysql:8.0
В этом примере поля depends_on
вызывают запуск служб в следующем порядке:
дб
API
веб-приложение
Зависимости каждой службы разрешаются рекурсивно. Служба, определяющая каждое поле depends_on
, запускается последней, в самом конце цепочки. Когда служба зависит от нескольких других контейнеров, они будут запущены в том порядке, в котором они перечислены в поле depends_on
.
Цепочка сервисов используется в обратном порядке, когда вы останавливаете стек с помощью docker-compose stop
. В приведенном выше примере сначала будет удален контейнер web-app
, затем api
и db
. Это предотвращает сбой запросов к контейнеру web-app
в начале операции удаления.
Ожидание готовности
Конфигурация depends_on
по умолчанию ожидает только запуска зависимых контейнеров. В приведенном выше примере Compose может создать контейнер api
сразу после запуска db
, даже если сервер базы данных внутри контейнера не готов принимать подключения. Это означает, что depends_on
редко бывает достаточно.
Вы можете комбинировать эту функцию с проверками работоспособности, чтобы предотвратить запуск контейнеров, пока их зависимости не будут фактически готовы. Чтобы использовать эту возможность, вложите поле condition
в depends_on
со значением service_healthy
:
services: api: image: example.com/api:latest depends_on: - db healthcheck: test: curl --fail http://127.0.0.1 || exit 1 interval: 10s retries: 5 start_period: 5s timeout: 10s web-app: image: example.com/web-app:latest depends_on: api: condition: service_healthy db: image: mysql:8.0
Теперь к контейнеру api
прикреплена команда проверки работоспособности. Служба веб-приложения
получает указание не запускаться до тех пор, пока не будет создан api
с успешным результатом проверки работоспособности. Это произойдет после того, как API начнет отвечать на запросы и команда curl
завершится с нулевым кодом состояния.
Ожидание успешного выхода из контейнера
В некоторых случаях ваша зависимость может быть одноразовым контейнером, который вы хотите запустить до завершения. Вы можете дождаться такой зависимости, установив в поле condition
значение service_completed_successfully
. Это полезно, когда у вас есть скрипт начальной установки, который выполняется в другом контейнере.
services: app: image: example.com/app:latest depends_on: config_builder: condition: service_completed_successfully volumes: - config:/opt/app/config config_builder: image: example.com/config_builder:latest env: - EXAMPLE_KEY - ANOTHER_KEY volumes: - config:/output volumes: config:
В этом примере показано, как зависимый образ может запустить команду, которая записывает файл конфигурации в общий том app
. После записи данных контейнер config_builder
останавливается с нулевым кодом выхода. Затем Compose автоматически запускает службу app
, поскольку условие ее зависимости выполнено.
Больше контроля с другими инструментами
В некоторых ситуациях depends_on
с условием
может быть недостаточно для вашего варианта использования. Вы можете добавить внешние инструменты для ручной проверки работоспособности и обработки ссылок между контейнерами.
Wait-for-It — это служебный скрипт, который обертывает другой процесс. Он запустит указанную вами команду после выполнения определенного условия. Это можно использовать для определения процедур проверки работоспособности независимо от встроенной поддержки Docker.
Вот как использовать healthcheck
, чтобы дождаться, пока связанный порт контейнера станет доступным:
services: api: image: example.com/api:latest depends_on: - db web-app: image: example.com/web-app:latest depends_on: - api command: ["./wait-for-it.sh", "api:8080", "--", "node", "app.js"] db: image: mysql:8.0
Здесь мы вернулись к тому, что Docker Compose только ожидает запуска контейнера api
. Служба веб-приложение
берет на себя ответственность за проверку работоспособности api
. Он использует скрипт Wait-for-It, чтобы определить, когда контейнер доступен через порт 8080. Затем Wait-for-It запустит реальную команду контейнера веб-приложения, определенную как node app.js
.
Этот подход лучше всего подходит для конкретных ситуаций, когда вы не можете настроить правильную проверку работоспособности с помощью Docker. Это может быть необходимо, если вы используете сторонний образ, который нельзя настроить для запуска команды проверки работоспособности. Функция ожидания позволяет определить, обслуживает ли порт трафик в качестве резервной замены. Хотя это и не безошибочно, это часто является хорошим показателем исправности контейнера.
Краткое содержание
Docker Compose по умолчанию одновременно запускает все службы в вашем стеке. Это часто нежелательно, когда связи между службами создают отношения зависимости родитель-потомок.
Поле depends_on
позволяет определить последовательность запуска ваших служб. Compose создаст каждый новый контейнер по порядку, гарантируя, что предыдущий будет запущен до того, как будет добавлен следующий контейнер.
Вы можете дождаться завершения работы предыдущего контейнера или сообщить о положительной проверке работоспособности, добавив условие
в определение зависимости. В ситуациях, когда проверка работоспособности не может быть использована, вы можете положиться на такие инструменты, как Wait-for-It, чтобы родительские контейнеры определяли, когда их зависимости готовы.