МАТЕРИАЛЫ КУРСА
СИИ • НАВИГАЦИЯ

Docker Compose - Управление многоконтейнерными приложениями

Полное руководство по Docker Compose для создания и управления сложными приложениями из нескольких контейнеров

~15 МИН ЧТЕНИЯ
ОБНОВЛЕНО НЕДАВНО

Docker Compose - Управление многоконтейнерными приложениями

Что такое Docker Compose?

Docker Compose - это инструмент для определения и запуска многоконтейнерных Docker-приложений. С помощью Compose вы можете использовать YAML-файл для конфигурации сервисов вашего приложения, а затем создать и запустить все сервисы одной командой.

Основные преимущества:

  • Простота управления - одна команда для всех сервисов
  • Декларативная конфигурация - описание инфраструктуры в коде
  • Изоляция окружений - разные конфигурации для разработки и продакшна
  • Автоматическое сетевое взаимодействие - контейнеры видят друг друга по именам

Установка Docker Compose

Проверка установки

Docker Compose обычно входит в состав Docker Desktop:

# Проверка версии
docker-compose --version

# Или в новых версиях Docker
docker compose version

Установка на Linux

# Скачивание последней версии
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# Добавление прав на выполнение
sudo chmod +x /usr/local/bin/docker-compose

# Создание символической ссылки
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

Основы docker-compose.yml

Структура файла

version: '3.8'  # Версия формата Compose

services:       # Определение сервисов
  service1:
    # конфигурация сервиса 1
  service2:
    # конфигурация сервиса 2

volumes:        # Определение томов (опционально)
  volume1:

networks:       # Определение сетей (опционально)
  network1:

Основные директивы

1. services

Определяет контейнеры, которые составляют ваше приложение:

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html
    environment:
      - ENV_VAR=value
    depends_on:
      - database
    restart: unless-stopped

2. Основные опции сервиса

  • image - используемый образ
  • build - путь к Dockerfile для сборки
  • ports - проброс портов
  • volumes - монтирование томов
  • environment - переменные окружения
  • depends_on - зависимости между сервисами
  • restart - политика перезапуска

Практические примеры

Пример 1: Простое веб-приложение

docker-compose.yml:

version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html
    restart: unless-stopped

  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
    restart: unless-stopped

Команды управления:

# Запуск всех сервисов
docker-compose up

# Запуск в фоновом режиме
docker-compose up -d

# Остановка всех сервисов
docker-compose down

# Просмотр статуса
docker-compose ps

# Просмотр логов
docker-compose logs
docker-compose logs web  # логи конкретного сервиса

Пример 2: Веб-приложение с базой данных

docker-compose.yml:

version: '3.8'

services:
  # Веб-приложение
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
      - DB_HOST=database
      - DB_PORT=5432
      - DB_NAME=myapp
      - DB_USER=postgres
      - DB_PASSWORD=password
    depends_on:
      - database
    volumes:
      - .:/app
      - /app/node_modules
    restart: unless-stopped

  # База данных PostgreSQL
  database:
    image: postgres:15-alpine
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
      - "5432:5432"
    restart: unless-stopped

  # Redis для кэширования
  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
    restart: unless-stopped

volumes:
  postgres_data:

Dockerfile для приложения:

FROM node:18-alpine

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "run", "dev"]

Пример 3: Полный стек приложения

docker-compose.yml:

version: '3.8'

services:
  # Nginx - обратный прокси
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/sites:/etc/nginx/sites-available
      - ./html:/var/www/html
    depends_on:
      - frontend
      - backend
    restart: unless-stopped

  # Frontend React приложение
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      - REACT_APP_API_URL=http://backend:5000
    depends_on:
      - backend
    restart: unless-stopped

  # Backend API
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://postgres:password@database:5432/myapp
      - REDIS_URL=redis://redis:6379
    depends_on:
      - database
      - redis
    restart: unless-stopped

  # PostgreSQL база данных
  database:
    image: postgres:15-alpine
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./database/init:/docker-entrypoint-initdb.d
    restart: unless-stopped

  # Redis
  redis:
    image: redis:alpine
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data
    restart: unless-stopped

  # Monitoring с Prometheus
  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
    restart: unless-stopped

volumes:
  postgres_data:
  redis_data:

networks:
  default:
    driver: bridge

Расширенные возможности

1. Переменные окружения

docker-compose.yml:

version: '3.8'

services:
  app:
    image: myapp:latest
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - API_KEY=${API_KEY}
    env_file:
      - .env
      - .env.local

.env файл:

DATABASE_URL=postgresql://user:password@localhost:5432/mydb
API_KEY=your_secret_api_key
NODE_ENV=development
PORT=3000

2. Множественные Compose файлы

docker-compose.yml (базовая конфигурация):

version: '3.8'

services:
  app:
    build: .
    environment:
      - NODE_ENV=development

  database:
    image: postgres:15-alpine
    environment:
      - POSTGRES_DB=myapp

docker-compose.prod.yml (продакшн расширение):

version: '3.8'

services:
  app:
    environment:
      - NODE_ENV=production
    restart: always

  database:
    restart: always
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Использование:

# Запуск с несколькими файлами
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

# Создание объединенного файла
docker-compose -f docker-compose.yml -f docker-compose.prod.yml config > docker-compose.final.yml

3. Healthchecks

version: '3.8'

services:
  app:
    image: myapp:latest
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

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

4. Secrets и Configs

version: '3.8'

services:
  app:
    image: myapp:latest
    secrets:
      - db_password
      - api_key
    configs:
      - source: app_config
        target: /app/config.yml

secrets:
  db_password:
    file: ./secrets/db_password.txt
  api_key:
    external: true

configs:
  app_config:
    file: ./configs/app.yml

Управление жизненным циклом

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

# Создание и запуск контейнеров
docker-compose up

# Пересборка образов
docker-compose up --build

# Запуск только определенного сервиса
docker-compose up database

# Масштабирование сервиса
docker-compose up --scale web=3

# Остановка сервисов
docker-compose stop

# Остановка и удаление контейнеров, сетей
docker-compose down

# Удаление с томами
docker-compose down -v

# Удаление с образами
docker-compose down --rmi all

# Перезапуск сервиса
docker-compose restart web

# Выполнение команды в сервисе
docker-compose exec web bash

# Просмотр логов
docker-compose logs -f web

# Мониторинг ресурсов
docker-compose top

Работа с профилями

version: '3.8'

services:
  app:
    image: myapp:latest
    profiles: ["production"]

  database:
    image: postgres:15-alpine

  monitoring:
    image: prometheus
    profiles: ["monitoring", "production"]

  development-tools:
    image: adminer
    profiles: ["development"]
# Запуск только основных сервисов
docker-compose up

# Запуск с профилем разработки
docker-compose --profile development up

# Запуск продакшн профиля
docker-compose --profile production up

Сетевое взаимодействие

Автоматические сети

По умолчанию Compose создает сеть для вашего приложения:

version: '3.8'

services:
  web:
    image: nginx:alpine
    # Доступен по имени 'web' для других сервисов

  app:
    image: myapp:latest
    environment:
      # Подключение к другому сервису по имени
      - DATABASE_URL=postgresql://user:password@database:5432/mydb

  database:
    image: postgres:15-alpine
    # Доступен по имени 'database'

Пользовательские сети

version: '3.8'

services:
  frontend:
    image: nginx:alpine
    networks:
      - frontend-network
      - backend-network

  backend:
    image: myapp:latest
    networks:
      - backend-network
      - database-network

  database:
    image: postgres:15-alpine
    networks:
      - database-network

networks:
  frontend-network:
    driver: bridge
  backend-network:
    driver: bridge
  database-network:
    driver: bridge
    internal: true  # Внутренняя сеть без доступа в интернет

Мониторинг и логирование

Централизованное логирование

docker-compose.yml:

version: '3.8'

services:
  app:
    image: myapp:latest
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  elasticsearch:
    image: elasticsearch:7.14.0
    environment:
      - discovery.type=single-node
    ports:
      - "9200:9200"

  logstash:
    image: logstash:7.14.0
    volumes:
      - ./logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf

  kibana:
    image: kibana:7.14.0
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200

Мониторинг с Prometheus и Grafana

version: '3.8'

services:
  app:
    image: myapp:latest
    ports:
      - "3000:3000"

  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/etc/prometheus/console_libraries'
      - '--web.console.templates=/etc/prometheus/consoles'

  grafana:
    image: grafana/grafana
    ports:
      - "3001:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana_data:/var/lib/grafana

volumes:
  grafana_data:

Разработка vs Продакшн

Конфигурация для разработки

docker-compose.dev.yml:

version: '3.8'

services:
  app:
    build:
      context: .
      target: development
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - DEBUG=*
    ports:
      - "3000:3000"
      - "9229:9229"  # Порт для отладки Node.js

  database:
    ports:
      - "5432:5432"  # Открываем порт для локального доступа

  redis:
    ports:
      - "6379:6379"

Конфигурация для продакшна

docker-compose.prod.yml:

version: '3.8'

services:
  app:
    build:
      context: .
      target: production
    environment:
      - NODE_ENV=production
    restart: always
    deploy:
      replicas: 3
      resources:
        limits:
          memory: 512M
        reservations:
          memory: 256M

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/prod.conf:/etc/nginx/nginx.conf
      - ./ssl:/etc/nginx/ssl
    restart: always

  database:
    restart: always
    volumes:
      - postgres_data:/var/lib/postgresql/data
    # Порты не открываем для безопасности

volumes:
  postgres_data:

Лучшие практики

1. Структура проекта

my-project/
├── docker-compose.yml
├── docker-compose.dev.yml
├── docker-compose.prod.yml
├── .env
├── .env.example
├── frontend/
│   ├── Dockerfile
│   ├── package.json
│   └── src/
├── backend/
│   ├── Dockerfile
│   ├── package.json
│   └── src/
├── nginx/
│   ├── nginx.conf
│   └── sites/
├── database/
│   └── init/
└── scripts/
    ├── start-dev.sh
    └── start-prod.sh

2. Многоэтапная сборка Docker образов

Dockerfile:

# Этап разработки
FROM node:18-alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]

# Этап сборки
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

# Продакшн этап
FROM node:18-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
EXPOSE 3000
CMD ["npm", "start"]

3. Использование .dockerignore

.dockerignore:

node_modules
npm-debug.log
.git
.gitignore
README.md
.env
.nyc_output
coverage
.nyc_output
.vscode

4. Безопасность

version: '3.8'

services:
  app:
    image: myapp:latest
    user: "1001:1001"  # Не используйте root
    read_only: true    # Только для чтения
    tmpfs:
      - /tmp
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE

  database:
    image: postgres:15-alpine
    environment:
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_password
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

Troubleshooting

Распространенные проблемы

1. Конфликты портов

# Проверка используемых портов
docker-compose ps
netstat -tulpn | grep :8080

# Изменение портов в docker-compose.yml
ports:
  - "8081:80"  # вместо 8080:80

2. Проблемы с сетью

# Пересоздание сетей
docker-compose down
docker network prune
docker-compose up

# Проверка сети
docker network ls
docker network inspect myproject_default

3. Проблемы с томами

# Проверка томов
docker volume ls
docker volume inspect myproject_postgres_data

# Очистка томов
docker-compose down -v

4. Отладка сервисов

# Подключение к контейнеру
docker-compose exec app bash

# Проверка логов
docker-compose logs -f app

# Проверка переменных окружения
docker-compose exec app env

# Проверка сетевой связности
docker-compose exec app ping database

Заключение

Docker Compose значительно упрощает управление многоконтейнерными приложениями. Основные преимущества:

  • Декларативная конфигурация - инфраструктура как код
  • Простота развертывания - одна команда для всего стека
  • Изоляция сред - разные конфигурации для разных этапов
  • Автоматическое масштабирование - легкое управление репликами

Начните с простых примеров и постепенно добавляйте сложность. Docker Compose станет незаменимым инструментом в вашем арсенале разработки и развертывания приложений.

ВСЕ МАТЕРИАЛЫ