5. Docker Compose

Docker Compose — инструмент для запуска мульти-контейнерных приложений. Один файл docker-compose.yml — и всё твоё окружение поднимается одной командой.
Зачем Compose?
Заголовок раздела «Зачем Compose?»Без Compose:docker network create mynetdocker run -d --network mynet --name db postgresdocker run -d --network mynet --name redis redisdocker run -d --network mynet -p 3000:3000 --env-file .env myapp
С Compose:docker compose up -d # всё готово!Базовый docker-compose.yml
Заголовок раздела «Базовый docker-compose.yml»services: app: build: . # собрать из Dockerfile ports: - "3000:3000" environment: - NODE_ENV=development - DATABASE_URL=postgresql://postgres:password@db:5432/mydb depends_on: - db - redis volumes: - .:/app # bind mount для hot reload - /app/node_modules # исключить node_modules
db: image: postgres:16-alpine environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: password POSTGRES_DB: mydb volumes: - postgres_data:/var/lib/postgresql/data ports: - "5432:5432" # только для локальной работы
redis: image: redis:7-alpine ports: - "6379:6379" volumes: - redis_data:/data
volumes: postgres_data: redis_data:Запуск и управление
Заголовок раздела «Запуск и управление»# Поднять все сервисы (в фоне)docker compose up -d
# Поднять с пересборкойdocker compose up -d --build
# Остановитьdocker compose stop
# Остановить и удалить контейнерыdocker compose down
# Остановить + удалить volumesdocker compose down -v
# Посмотреть статусdocker compose ps
# Логи всех сервисовdocker compose logs
# Логи конкретного сервисаdocker compose logs appdocker compose logs -f app # следить в реальном времени
# Зайти в контейнерdocker compose exec app shdocker compose exec db psql -U postgres mydb
# Запустить командуdocker compose run app npm run migrateProduction vs Development конфиги
Заголовок раздела «Production vs Development конфиги»# docker-compose.yml (base)services: app: image: myapp environment: - PORT=3000
db: image: postgres:16-alpine volumes: - postgres_data:/var/lib/postgresql/data
volumes: postgres_data:# docker-compose.dev.yml (override для development)services: app: build: . # собираем локально volumes: - .:/app # hot reload - /app/node_modules environment: - NODE_ENV=development ports: - "3000:3000" - "9229:9229" # debug port
db: ports: - "5432:5432" # открываем порт для DBeaver/TablePlus# docker-compose.prod.yml (override для production)services: app: image: ghcr.io/myorg/myapp:latest # готовый образ restart: unless-stopped environment: - NODE_ENV=production
db: restart: unless-stopped# Запуск в developmentdocker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
# Запуск в productiondocker compose -f docker-compose.yml -f docker-compose.prod.yml up -dHealth checks
Заголовок раздела «Health checks»services: app: image: myapp depends_on: db: condition: service_healthy # ждёт healthy redis: condition: service_healthy
db: image: postgres:16-alpine healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 start_period: 10s
redis: image: redis:7-alpine healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5Полный production stack
Заголовок раздела «Полный production stack»services: nginx: image: nginx:alpine ports: - "80:80" - "443:443" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro - ./ssl:/etc/nginx/ssl:ro - static_files:/var/www/static depends_on: - app restart: unless-stopped
app: image: ghcr.io/myorg/myapp:${APP_VERSION:-latest} environment: - NODE_ENV=production - DATABASE_URL=${DATABASE_URL} - REDIS_URL=redis://redis:6379 - SECRET_KEY=${SECRET_KEY} depends_on: db: condition: service_healthy restart: unless-stopped deploy: replicas: 2 # два экземпляра update_config: parallelism: 1 delay: 10s restart_policy: condition: on-failure max_attempts: 3
db: image: postgres:16-alpine environment: POSTGRES_USER: ${DB_USER} POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_DB: ${DB_NAME} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped
redis: image: redis:7-alpine command: redis-server --requirepass ${REDIS_PASSWORD} volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "--no-auth-warning", "-a", "${REDIS_PASSWORD}", "ping"] interval: 10s retries: 5 restart: unless-stopped
volumes: postgres_data: redis_data: static_files:.env файлы с Compose
Заголовок раздела «.env файлы с Compose»# .env (автоматически читается Compose)APP_VERSION=1.2.3DATABASE_URL=postgresql://user:pass@db:5432/mydbDB_USER=myuserDB_PASSWORD=secretpasswordDB_NAME=mydbREDIS_PASSWORD=redispassSECRET_KEY=supersecretkey# В docker-compose.ymlservices: app: env_file: - .env # все переменные из файла - .env.local # локальные переопределения environment: - ADDITIONAL_VAR=value # дополнительныеКлючевые моменты
Заголовок раздела «Ключевые моменты»- Docker Compose — для мульти-контейнерных приложений
docker compose up -d— запустить всё в фонеdepends_onсcondition: service_healthy— дождаться готовности сервиса- Override файлы — разные конфиги для dev и prod
.env— автоматически подхватывается Compose- Volumes — персистентное хранение данных (БД)
restart: unless-stopped— автоперезапуск в production
Интерактивный пример
Заголовок раздела «Интерактивный пример»Визуализация сервисов Docker Compose и их связей: