🧩 Docker Compose
Полный справочник: файл compose.yaml (сервисы, сети, тома, переменные, healthcheck, profiles, ресурсы), команды, окружения dev/prod, паттерны и отладка.
Шпаргалки · Инфраструктура · #docker #compose #containers #devops
Идея
Compose описывает несколько контейнеров приложения одним YAML-файлом и управляет ими командами: сервисы, сети, тома, переменные, порядок запуска. Подходит для локальной разработки, тестов, CI и небольших серверов. Для кластеров смотрите Swarm и Kubernetes.
Файл называется compose.yaml (или compose.yml, docker-compose.yml). Команда docker compose (плагин v2); старая docker-compose (v1) устарела. Ключ version: больше не нужен.
Команды
docker compose up docker compose up -d docker compose up -d --build
docker compose up -d --force-recreate docker compose up --no-deps -d web # пересоздать один сервис
docker compose down docker compose down -v --rmi local # с томами и образами
docker compose ps [-a] docker compose top docker compose images
docker compose logs -f --tail 100 web docker compose exec web sh docker compose run --rm web npm test
docker compose build [--no-cache] web docker compose pull docker compose push
docker compose start|stop|restart web docker compose pause|unpause web docker compose kill web
docker compose config # итоговый файл после подстановок (проверка)
docker compose --profile debug up docker compose -p myproj up # имя проекта
docker compose watch # автообновление при изменении файлов (develop.watch)
docker compose cp web:/app/log.txt . docker compose events docker compose port web 80
Полный пример
name: shop
services:
web:
build:
context: ./web
dockerfile: Dockerfile
target: prod
args: { NODE_ENV: production }
image: ghcr.io/me/shop-web:${TAG:-latest}
ports: ["8080:3000"] # "127.0.0.1:8080:3000" — только localhost
environment:
DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/app
REDIS_URL: redis://cache:6379
env_file: [.env]
depends_on:
db: { condition: service_healthy }
cache: { condition: service_started }
restart: unless-stopped
networks: [front, back]
volumes:
- ./web/uploads:/app/uploads
- logs:/var/log/app
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
interval: 10s
timeout: 3s
retries: 5
start_period: 20s
deploy:
resources: { limits: { cpus: "1.0", memory: 512M } }
develop:
watch:
- { action: sync, path: ./web/src, target: /app/src }
- { action: rebuild, path: ./web/package.json }
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: app
volumes:
- dbdata:/var/lib/postgresql/data
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app"]
interval: 5s
retries: 10
networks: [back]
cache:
image: redis:7-alpine
command: ["redis-server", "--appendonly", "yes"]
volumes: [cachedata:/data]
networks: [back]
adminer:
image: adminer
profiles: ["debug"]
ports: ["8081:8080"]
networks: [back]
networks:
front:
back:
internal: true # без выхода наружу
volumes:
dbdata:
cachedata:
logs:
secrets:
db_password: { file: ./secrets/db_password.txt }
Основные ключи сервиса
| Ключ | Назначение |
|---|---|
image / build |
готовый образ или сборка из Dockerfile |
ports |
"хост:контейнер" публикация наружу |
expose |
порт только для других сервисов сети |
environment, env_file |
переменные окружения |
volumes |
тома (имя:/путь) и bind mount (./папка:/путь[:ro]) |
networks, network_mode |
сети |
depends_on |
порядок и условие запуска (service_started, service_healthy, service_completed_successfully) |
command, entrypoint, working_dir, user |
запуск |
restart |
no, always, on-failure, unless-stopped |
healthcheck |
проверка здоровья |
deploy.resources |
лимиты CPU и памяти |
profiles |
необязательные группы сервисов |
secrets, configs |
секреты и конфиги как файлы |
extra_hosts, dns, hostname, container_name |
сетевые мелочи |
cap_drop, read_only, security_opt, tmpfs |
усиление безопасности |
scale / deploy.replicas |
число копий сервиса |
labels, logging, ulimits, sysctls, init, stop_grace_period |
прочее |
Сети и имена
Compose создаёт сеть проекта, и сервисы видят друг друга по имени сервиса (db, cache). Наружу открывайте порты только у тех сервисов, к которым нужен доступ с хоста. depends_on сам по себе ждёт только запуск контейнера: для готовности используйте condition: service_healthy и healthcheck.
Переменные
${VAR},${VAR:-значение по умолчанию},${VAR:?ошибка, если не задана}подставляются из окружения оболочки и файла.envрядом сcompose.yaml.environmentзадаёт переменные внутри контейнера,env_fileчитает файл целиком.- Порядок приоритета: значения оболочки, затем
--env-file, затем.env. - Не коммитьте
.envс секретами: храните.env.example. - Секреты лучше как файлы:
secrets:и/run/secrets/<имя>, а в приложении читайте*_FILE.
Несколько файлов и окружения
docker compose -f compose.yaml -f compose.dev.yaml up -d # поверх базового
docker compose -f compose.yaml -f compose.prod.yaml config # проверить итог
compose.override.yaml подхватывается автоматически: хранит dev-настройки (bind mount, отладочные порты). Расширение: extends, include, якоря YAML:
x-logging: &logging { driver: json-file, options: { max-size: "10m", max-file: "3" } }
services:
web: { logging: *logging }
api: { logging: *logging }
Типовые связки
| Задача | Состав |
|---|---|
| Веб + БД | web, postgres (volume), adminer (profile debug) |
| Реверс-прокси | caddy или nginx / traefik + приложение во внутренней сети |
| Очереди | rabbitmq (management) или kafka + zookeeper/KRaft |
| Мониторинг | prometheus + grafana + node-exporter + cadvisor |
| Логи | loki + promtail + grafana |
| Тесты в CI | docker compose up -d --wait затем тесты, down -v |
--wait ждёт, пока сервисы с healthcheck станут здоровыми.
Отладка
| Симптом | Что проверить |
|---|---|
Сервис не видит БД по localhost |
используйте имя сервиса (db), не localhost |
| Приложение стартует раньше БД | healthcheck + depends_on: condition: service_healthy, повторные подключения в коде |
| Правки конфигурации не применились | docker compose up -d пересоздаёт при изменении; образы пересобирайте --build |
| Данные пропали | down -v удаляет тома; используйте именованные тома |
| Порт занят | поменяйте левую часть ports или остановите конфликтующий процесс |
| Права на bind mount | UID / GID, user:, chown |
| Странное поведение переменных | docker compose config показывает итоговые значения |
| Много места | docker system df, docker compose down --rmi local |
Production
Compose годится для одного сервера: фиксируйте версии образов, restart: unless-stopped, лимиты ресурсов, healthcheck, вращение логов, резервные копии томов, HTTPS на прокси, секреты вне образов. Для нескольких серверов, самовосстановления и обновлений без простоя переходите на Docker Swarm или Kubernetes (инструмент kompose помогает конвертировать).