Содержание

Зачем нужен Docker Compose

В реальных приложениях несколько сервисов: бэкенд, фронтенд, база данных, Redis, очередь задач. Запускать каждый вручную через docker run — неудобно. Compose описывает все сервисы в одном файле и запускает их одной командой. (Основы — в гайде Docker для новичка, образы — в статье про Dockerfile.)

Структура docker-compose.yml

version: '3.9'

services:       # Список сервисов (контейнеров)
  app:
    build: .
    ports:
      - "3000:3000"

networks:       # Кастомные сети (опционально)
  backend:

volumes:        # Именованные тома для хранения данных
  pgdata:

Полный пример: приложение + PostgreSQL + Redis

version: '3.9'

services:

  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production
      DATABASE_URL: postgres://user:secret@db:5432/myapp
      REDIS_URL: redis://cache:6379
    depends_on:
      db:
        condition: service_healthy    # Ждём пока база готова
      cache:
        condition: service_started
    networks:
      - backend
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: myapp
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user -d myapp"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - backend

  cache:
    image: redis:7-alpine
    volumes:
      - redisdata:/data
    networks:
      - backend

networks:
  backend:
    driver: bridge

volumes:
  pgdata:
  redisdata:

Переменные окружения через .env

Не хардкоди секреты прямо в docker-compose.yml. Используй .env файл (и не забудь добавить его в .gitignore):

# .env
POSTGRES_USER=user
POSTGRES_PASSWORD=supersecret
POSTGRES_DB=myapp
APP_PORT=3000
# docker-compose.yml
services:
  db:
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
  app:
    ports:
      - "${APP_PORT}:3000"

⚠️ Добавь .env в .gitignore! Для CI/CD используй .env.example с заглушками.

Health checks — ждём готовности сервиса

Без depends_on + condition бэкенд стартует раньше чем поднимется база, получает ошибку подключения и падает.

db:
  healthcheck:
    test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
    interval: 10s     # Проверять каждые 10 сек
    timeout: 5s       # Таймаут одной проверки
    retries: 5        # После 5 неудач — unhealthy
    start_period: 30s # Не считать неудачи первые 30 сек

Профили — разные конфигурации для dev и prod

services:
  app:
    build: .
    # Без профиля — запускается всегда

  pgadmin:
    image: dpage/pgadmin4
    profiles:
      - dev          # Только в dev-режиме
    ports:
      - "5050:80"

  nginx:
    image: nginx:alpine
    profiles:
      - prod         # Только в продакшне
# Запустить только dev-профиль
docker-compose --profile dev up -d

# Запустить prod-профиль
docker-compose --profile prod up -d

Основные команды

# Запустить всё в фоне
docker-compose up -d

# Посмотреть логи всех сервисов
docker-compose logs -f

# Логи конкретного сервиса
docker-compose logs -f app

# Выполнить команду в запущенном контейнере
docker-compose exec app sh

# Остановить без удаления данных
docker-compose stop

# Остановить и удалить контейнеры (данные в volumes остаются)
docker-compose down

# Удалить всё включая volumes (ОСТОРОЖНО — удалит данные БД!)
docker-compose down -v

💡 Для локальной разработки создай docker-compose.override.yml — он автоматически мержится с основным файлом и позволяет монтировать код для hot-reload без изменения основного compose-файла.

Поделиться: