Перейти к содержимому

5. Docker Compose

Иллюстрация к уроку

Docker Compose — инструмент для запуска мульти-контейнерных приложений. Один файл docker-compose.yml — и всё твоё окружение поднимается одной командой.

Без Compose:
docker network create mynet
docker run -d --network mynet --name db postgres
docker run -d --network mynet --name redis redis
docker run -d --network mynet -p 3000:3000 --env-file .env myapp
С Compose:
docker compose up -d # всё готово!
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
# Остановить + удалить volumes
docker compose down -v
# Посмотреть статус
docker compose ps
# Логи всех сервисов
docker compose logs
# Логи конкретного сервиса
docker compose logs app
docker compose logs -f app # следить в реальном времени
# Зайти в контейнер
docker compose exec app sh
docker compose exec db psql -U postgres mydb
# Запустить команду
docker compose run app npm run migrate
# 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
Окно терминала
# Запуск в development
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
# Запуск в production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
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
docker-compose.prod.yml
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)
APP_VERSION=1.2.3
DATABASE_URL=postgresql://user:pass@db:5432/mydb
DB_USER=myuser
DB_PASSWORD=secretpassword
DB_NAME=mydb
REDIS_PASSWORD=redispass
SECRET_KEY=supersecretkey
# В docker-compose.yml
services:
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 и их связей: