Как в docker-compose сделать так, чтобы контейнер не принимал пользовательский трафик до полной готовности сервиса?

«Как в docker-compose сделать так, чтобы контейнер не принимал пользовательский трафик до полной готовности сервиса?» — вопрос из категории Docker, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для этого используется комбинация healthcheck и depends_on с условием service_healthy. Healthcheck периодически проверяет готовность сервиса, и только после успешной проверки контейнер считается готовым к работе.

Пример конфигурации docker-compose.yml:

services:
  app:
    image: myapp:latest
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 30s
    depends_on:
      database:
        condition: service_healthy
      cache:
        condition: service_started

  database:
    image: postgres:15
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5

Почему это важно:

  • Без healthcheck балансировщик нагрузки или другие сервисы могут направлять трафик на контейнер, который еще инициализирует БД или загружает конфигурацию
  • start_period дает время на первоначальный запуск перед началом проверок
  • В production часто дополняю entrypoint-скриптом, который явно дожидается зависимых сервисов:
#!/bin/bash
# wait-for.sh
until nc -z database 5432; do
  echo "Waiting for database..."
  sleep 2
done

echo "All dependencies ready, starting app..."
exec "$@"

Альтернативы:

  • Для HTTP-сервисов можно использовать startupProbe в Kubernetes
  • Инструменты вроде wait-for-it или dockerize для сложных сценариев ожидания