Docker Compose - Управление многоконтейнерными приложениями
Полное руководство по Docker Compose для создания и управления сложными приложениями из нескольких контейнеров
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 станет незаменимым инструментом в вашем арсенале разработки и развертывания приложений.