Базовый docker-compose.yml — это старт. Для production нужны healthcheck, профили, override-файлы и управление ресурсами.
healthcheck для depends_on
По умолчанию depends_on гарантирует только запуск контейнера, но не готовность сервиса. Postgres может стартовать, но ещё принимать соединения. Решение — healthcheck.
services:
db:
image: postgres:15
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s # как часто проверять
timeout: 3s # таймаут одной проверки
retries: 5 # сколько раз повторить
start_period: 10s # пауза перед первой проверкой
web:
build: .
depends_on:
db:
condition: service_healthy # ждать healthcheck
Варианты condition:
- service_started — контейнер запущен (по умолчанию)
- service_healthy — прошёл healthcheck
- service_completed_successfully — завершился с кодом 0 (для init-контейнеров)
Примеры healthcheck для разных сервисов:
# Redis
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 3
# HTTP-сервис
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
profiles: dev/prod конфигурации
Profiles позволяют определить сервисы, которые запускаются только в конкретных сценариях.
services:
web:
build: .
ports:
- "8000:8000"
# Без профиля — запускается всегда
db:
image: postgres:15
# Без профиля — запускается всегда
pgadmin:
image: dpage/pgadmin4
profiles: [dev] # только в dev
ports:
- "5050:80"
mailhog:
image: mailhog/mailhog
profiles: [dev] # только в dev
ports:
- "8025:8025"
nginx:
image: nginx:alpine
profiles: [prod] # только в prod
ports:
- "80:80"
- "443:443"
# Запуск только базовых сервисов
docker compose up -d
# Запуск с dev-профилем
docker compose --profile dev up -d
# Несколько профилей
docker compose --profile dev --profile monitoring up -d
Override: docker-compose.override.yml
Docker Compose автоматически загружает docker-compose.override.yml и мержит его с основным файлом. Удобно для локальных настроек разработчика.
# docker-compose.yml — общий, коммитится в git
services:
web:
build: .
ports:
- "8000:8000"
environment:
LOG_LEVEL: info
db:
image: postgres:15
# docker-compose.override.yml — локальный, в .gitignore
services:
web:
volumes:
- .:/app # live reload: монтируем код в контейнер
environment:
LOG_LEVEL: debug
DEBUG: "true"
command: python manage.py runserver 0.0.0.0:8000
db:
ports:
- "5432:5432" # в dev: postgres доступен с хоста
Явное указание файлов:
# Использовать конкретные файлы
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# Только основной файл (без автоматического override)
docker compose -f docker-compose.yml up -d
Переменные и интерполяция ${VAR}
# docker-compose.yml
services:
web:
image: ${REGISTRY:-docker.io}/${IMAGE_NAME}:${IMAGE_TAG:-latest}
ports:
- "${APP_PORT:-8000}:8000"
deploy:
replicas: ${WEB_REPLICAS:-1}
Синтаксис подстановок:
- ${VAR} — значение переменной, ошибка если не задана
- ${VAR:-default} — значение или дефолт если не задана
- ${VAR:?error message} — ошибка с сообщением если не задана
# Проверить итоговую конфигурацию после подстановок
docker compose config
deploy: ресурсы и реплики
Секция deploy управляет распределением ресурсов (актуально для Docker Swarm и Compose v3+, частично работает в локальном Compose).
services:
web:
build: .
deploy:
replicas: 3 # количество копий сервиса
update_config:
parallelism: 1 # обновлять по одной реплике
delay: 10s # пауза между репликами
restart_policy:
condition: on-failure
max_attempts: 3
resources:
limits:
cpus: "0.5" # не более 50% одного ядра
memory: 512M # не более 512 МБ RAM
reservations:
cpus: "0.1"
memory: 128M
db:
image: postgres:15
deploy:
resources:
limits:
memory: 1G
reservations:
memory: 256M
Лимиты ресурсов — важная защита от ситуации, когда один контейнер “съедает” всю память хоста.
Команды управления
# Запуск
docker compose up -d # запустить в фоне
docker compose up -d --build # с пересборкой образов
docker compose up -d web db # только конкретные сервисы
# Остановка
docker compose down # остановить и удалить контейнеры
docker compose down -v # также удалить volumes
docker compose down --rmi local # также удалить локальные образы
docker compose stop web # остановить сервис без удаления
# Логи
docker compose logs -f # все логи в реальном времени
docker compose logs -f web # логи конкретного сервиса
docker compose logs --tail=100 web # последние 100 строк
# Выполнение команд
docker compose exec web bash # войти в контейнер
docker compose exec web python manage.py migrate
docker compose run --rm web pytest # запустить одноразовый контейнер
# Масштабирование
docker compose up -d --scale web=3 # запустить 3 копии web
# Информация
docker compose ps # статус всех сервисов
docker compose top # процессы внутри контейнеров
docker compose images # образы сервисов
docker compose port web 8000 # узнать проброшенный порт
Полный пример: production-like стек
version: "3.8"
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
web:
condition: service_healthy
profiles: [prod]
web:
build: .
image: ${IMAGE_NAME:-myapp}:${IMAGE_TAG:-latest}
environment:
DATABASE_URL: postgresql://${DB_USER}:${DB_PASS}@db:5432/${DB_NAME}
SECRET_KEY: ${SECRET_KEY}
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 20s
deploy:
replicas: ${WEB_REPLICAS:-2}
resources:
limits:
cpus: "1.0"
memory: 512M
db:
image: postgres:15
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASS}
POSTGRES_DB: ${DB_NAME}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
interval: 5s
timeout: 3s
retries: 5
deploy:
resources:
limits:
memory: 1G
volumes:
pgdata:
💬 Комментарии (0)
Комментариев пока нет
Станьте первым, кто поделится мнением об этой статье!