Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Docker Compose
docker_compose

Docker Compose

Оркестрация многоконтейнерных приложений с помощью Docker Compose

Docker Compose

Многоконтейнерные приложения требуют оркестрации. Docker Compose позволяет описывать и запускать сложные приложения одной командой.

#Что такое Docker Compose?

Docker Compose — инструмент для определения и запуска многоконтейнерных приложений Docker. Использует YAML-файл для описания:

  • Сервисов (контейнеров)
  • Сетей
  • Томов (хранилищ)
  • Зависимостей между сервисами

Преимущества:

  • Вся конфигурация приложения в одном файле
  • Запуск одной командой (docker-compose up)
  • Воспроизводимость окружения
  • Удобство для разработки и тестирования

#Установка

Docker Compose v2 встроен в Docker Desktop и современные версии Docker CLI:

# Проверка версии docker compose version # Docker Compose version v2.20.0 # Старый синтаксис (v1, устарел) docker-compose version

Важно: В Docker Compose v2 используется docker compose (без дефиса).

#Базовая структура docker-compose.yml

version: '3.8' services: web: image: nginx:alpine ports: - "80:80" depends_on: - api api: build: ./api environment: - DATABASE_URL=postgresql://user:pass@db:5432/myapp depends_on: - db db: image: postgres:15 environment: POSTGRES_USER: user POSTGRES_PASSWORD: pass POSTGRES_DB: myapp volumes: - postgres-data:/var/lib/postgresql/data volumes: postgres-data: networks: default: driver: bridge

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

#version

Версия формата Compose файла. Для Docker Compose v2 можно не указывать.

version: '3.8' # Опционально для v2

#services

Определяет контейнеры приложения.

services: web: image: nginx api: build: ./api db: image: postgres

#image vs build

image — использовать готовый образ:

services: nginx: image: nginx:alpine postgres: image: postgres:15

build — собирать образ из Dockerfile:

services: api: build: ./api # или с контекстом и dockerfile build: context: ./api dockerfile: Dockerfile.prod args: - NODE_ENV=production

#ports

Публикация портов:

services: web: ports: - "8080:80" # host:container - "443:443" - "127.0.0.1:9000:9000" # только localhost

#environment

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

services: api: environment: - DATABASE_URL=postgresql://db:5432/myapp - REDIS_HOST=redis - DEBUG=true # Или из файла env_file: - .env - .env.production

Файл .env:

DATABASE_URL=postgresql://db:5432/myapp
REDIS_HOST=redis
DEBUG=true

#volumes

Монтирование хранилищ:

services: db: volumes: - postgres-data:/var/lib/postgresql/data - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro app: volumes: - ./src:/app/src - /app/node_modules volumes: postgres-data:

#depends_on

Зависимости между сервисами:

services: web: depends_on: - api api: depends_on: - db - redis

Важно: depends_on гарантирует порядок запуска, но не ожидает готовности сервиса.

Для ожидания готовности используйте health checks:

services: api: depends_on: db: condition: service_healthy redis: condition: service_started db: image: postgres:15 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5

#networks

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

services: frontend: networks: - frontend-network api: networks: - frontend-network - backend-network db: networks: - backend-network networks: frontend-network: driver: bridge backend-network: driver: bridge internal: true # Нет доступа извне

#Команды Docker Compose

#Запуск приложения

# Запуск в фоновом режиме docker compose up -d # Запуск в foreground (логи в терминал) docker compose up # Запуск с пересборкой образов docker compose up -d --build # Запуск конкретных сервисов docker compose up -d api db # Запуск с удалением старых контейнеров docker compose up -d --force-recreate

#Остановка приложения

# Остановка сервисов docker compose stop # Остановка и удаление контейнеров docker compose down # Остановка, удаление контейнеров и volumes docker compose down -v # Остановка, удаление контейнеров и образов docker compose down --rmi all

#Просмотр состояния

# Статус сервисов docker compose ps # Логи сервисов docker compose logs docker compose logs -f # follow docker compose logs api # конкретный сервис docker compose logs -f api db # несколько сервисов # Использование ресурсов docker compose top

#Выполнение команд

# Выполнить команду в сервисе docker compose exec api bash docker compose exec db psql -U postgres # Запустить новую задачу docker compose run --rm api python manage.py migrate

#Пересборка

# Пересобрать образы docker compose build # Пересобрать без кэша docker compose build --no-cache # Пересобрать конкретный сервис docker compose build api

#Профили

Профили позволяют запускать разные конфигурации:

services: web: image: nginx api: image: myapi # Сервис только для разработки mailhog: image: mailhog/mailhog profiles: - dev # Сервис для тестирования test-runner: image: myapp-test profiles: - test # Запуск docker compose up -d # web, api docker compose --profile dev up # web, api, mailhog docker compose --profile test up # web, api, test-runner

#Переопределение конфигурации

#Multiple Compose files

# Базовая конфигурация docker-compose.yml # Переопределение для dev docker-compose.dev.yml # Переопределение для prod docker-compose.prod.yml
# docker-compose.yml services: api: image: myapi:latest ports: - "8000:8000" # docker-compose.dev.yml services: api: volumes: - ./src:/app/src environment: - DEBUG=true # docker-compose.prod.yml services: api: deploy: replicas: 3 environment: - DEBUG=false
# Запуск с переопределением docker compose -f docker-compose.yml -f docker-compose.dev.yml up

Файлы применяются по порядку, последующие переопределяют предыдущие.

#Переменные окружения в Compose

#Интерполяция переменных

services: api: image: myapi:${TAG:-latest} environment: - PORT=${PORT:-8000}
# Установка переменных export TAG=v1.0.0 export PORT=9000 docker compose up # Или через .env файл # .env автоматически загружается

#.env файл

# .env
POSTGRES_VERSION=15
API_TAG=v1.0.0
DEBUG=false
# docker-compose.yml services: db: image: postgres:${POSTGRES_VERSION} api: image: myapi:${API_TAG}

#Best Practices

#1. Используйте .env для чувствительных данных

# ✅ Хорошо services: api: environment: - DATABASE_URL=${DATABASE_URL} - SECRET_KEY=${SECRET_KEY} # .env (добавить в .gitignore) DATABASE_URL=postgresql://user:pass@db:5432/myapp SECRET_KEY=super-secret-key
# ❌ Плохо — секреты в compose файле services: api: environment: - DATABASE_URL=postgresql://user:password123@db:5432/myapp

#2. Используйте health checks

services: db: image: postgres:15 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 start_period: 30s api: depends_on: db: condition: service_healthy

#3. Ограничивайте ресурсы

services: api: image: myapi deploy: resources: limits: cpus: '1' memory: 512M reservations: cpus: '0.5' memory: 256M

#4. Используйте restart policies

services: api: restart: unless-stopped db: restart: always

#5. Именуйте volumes явно

# ✅ Хорошо services: db: volumes: - postgres-data:/var/lib/postgresql/data volumes: postgres-data: # ❌ Плохо — anonymous volume services: db: volumes: - /var/lib/postgresql/data

#6. Используйте .dockerignore

# .dockerignore
.env
*.log
__pycache__
node_modules
.git

#7. Разделяйте конфигурации

# Структура проекта
docker-compose.yml          # Базовая конфигурация
docker-compose.dev.yml      # Разработка
docker-compose.test.yml     # Тесты
docker-compose.prod.yml     # Production

#Практика: Full-stack приложение

#Структура

myapp/
├── frontend/
│   ├── Dockerfile
│   ├── package.json
│   └── src/
├── backend/
│   ├── Dockerfile
│   ├── requirements.txt
│   └── app/
├── docker-compose.yml
└── .env

#docker-compose.yml

version: '3.8' services: frontend: build: ./frontend ports: - "3000:80" depends_on: - backend networks: - frontend-network backend: build: ./backend environment: - DATABASE_URL=postgresql://user:pass@db:5432/myapp - REDIS_URL=redis://redis:6379 depends_on: db: condition: service_healthy redis: condition: service_started networks: - frontend-network - backend-network db: image: postgres:15-alpine environment: POSTGRES_USER: user POSTGRES_PASSWORD: pass POSTGRES_DB: myapp volumes: - postgres-data:/var/lib/postgresql/data networks: - backend-network healthcheck: test: ["CMD-SHELL", "pg_isready -U user"] interval: 10s timeout: 5s retries: 5 redis: image: redis:7-alpine networks: - backend-network volumes: postgres-data: networks: frontend-network: driver: bridge backend-network: driver: bridge internal: true

#Запуск

# Сборка и запуск docker compose up -d --build # Проверка статуса docker compose ps # Логи docker compose logs -f backend # Остановка docker compose down

#Troubleshooting

#Сервис не запускается

# Проверить логи docker compose logs service_name # Проверить конфигурацию docker compose config # Запустить в foreground для отладки docker compose up service_name

#Проблемы с подключением между сервисами

# Проверить сеть docker compose exec service_name ping other_service # Проверить переменные окружения docker compose exec service_name env # Проверить, запущен ли сервис docker compose ps

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

# Освободить порт lsof -i :8000 kill <PID> # Или изменить порт в compose ports: - "8001:8000" # Использовать другой порт хоста

#Продвинутые техники

#Override файлов через COMPOSE_FILE

Вместо явного указания файлов используйте переменную окружения:

# .env COMPOSE_FILE=docker-compose.yml:docker-compose.dev.yml # или для Windows COMPOSE_FILE=docker-compose.yml;docker-compose.dev.yml
# Запуск без явного указания файлов docker compose up -d

#Переопределение через docker-compose.override.yml

Docker Compose автоматически загружает docker-compose.override.yml если он существует:

# Структура docker-compose.yml # Базовая конфигурация docker-compose.override.yml # Автоматически применяется при запуске
# docker-compose.override.yml services: api: volumes: - ./src:/app/src environment: - DEBUG=true
# Автоматически применит оба файла docker compose up -d

Идеально для: локальной разработки, чтобы не забывать флаги -f.

#Динамическое конфигурирование через env_file

services: api: env_file: - .env.${ENVIRONMENT:-development}
# .env.development DEBUG=true LOG_LEVEL=debug # .env.production DEBUG=false LOG_LEVEL=error # Запуск ENVIRONMENT=production docker compose up -d

#Сложные health checks

services: postgres: image: postgres:15 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 start_period: 30s mysql: image: mysql:8.0 healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"] interval: 10s timeout: 5s retries: 5 start_period: 60s redis: image: redis:7 healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 web: image: nginx healthcheck: test: ["CMD", "curl", "-f", "http://localhost/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s api: build: ./api healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/healthcheck"] interval: 15s timeout: 10s retries: 5 start_period: 60s

#Wait для готовности сервисов

Альтернатива health checks — утилита wait-for-it.sh или dockerize:

services: api: build: ./api command: > sh -c "./wait-for-it.sh db:5432 --timeout=60 --strict -- python manage.py migrate && python manage.py runserver 0.0.0.0:8000" depends_on: - db
# wait-for-it.sh (скачать и добавить в образ) # https://github.com/vishnubob/wait-for-it

Или через dockerize:

# Dockerfile FROM python:3.11 RUN wget https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz \ && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-v0.6.1.tar.gz \ && rm dockerize-linux-amd64-v0.6.1.tar.gz CMD ["dockerize", "-wait", "tcp://db:5432", "-timeout", "60s", "python", "manage.py", "runserver"]

#Init-контейнеры

Эмуляция init-контейнеров через сервисы:

services: db-migrate: build: ./api command: python manage.py migrate environment: - DATABASE_URL=postgresql://user:pass@db:5432/myapp depends_on: db: condition: service_healthy restart: "no" api: build: ./api command: python manage.py runserver 0.0.0.0:8000 depends_on: db-migrate: condition: service_completed_successfully environment: - DATABASE_URL=postgresql://user:pass@db:5432/myapp db: image: postgres:15 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5

#Secrets для production

# docker-compose.prod.yml services: api: image: myapi secrets: - db_password - api_key secrets: db_password: external: true api_key: file: ./secrets/api_key.txt
# Создание секретов echo "super-secret-password" | docker secret create db_password - docker secret create api_key ./secrets/api_key.txt # Использование в контейнере docker compose exec api cat /run/secrets/db_password

#Deploy для Docker Swarm

services: api: image: myapi:latest deploy: replicas: 3 update_config: parallelism: 1 delay: 10s order: start-first rollback_config: parallelism: 1 delay: 10s resources: limits: cpus: '1' memory: 512M reservations: cpus: '0.5' memory: 256M restart_policy: condition: on-failure delay: 5s max_attempts: 3 window: 120s placement: constraints: - node.role == manager - node.labels.type == api labels: - "com.example.description=API Service"
# Развёртывание в Swarm docker stack deploy -c docker-compose.prod.yml myapp # Проверка docker stack ps myapp docker service ls

#Логирование

services: api: image: myapi logging: driver: "json-file" options: max-size: "10m" max-file: "3" compress: "true" # Отправка в syslog syslog-service: image: myapp logging: driver: syslog options: syslog-address: "udp://syslog.example.com:514" tag: "myapp" # Отправка в journald journald-service: image: myapp logging: driver: journald # Отключение логирования no-logs: image: myapp logging: driver: none

#Build contexts и таргеты

services: api: build: context: ./api dockerfile: Dockerfile target: production # Multi-stage build target args: - VERSION=1.0.0 - BUILD_DATE=2024-01-01 cache_from: - myapi:cache extra_hosts: - "github.com:140.82.121.4" secrets: - npm_token tags: - myapi:latest - myapi:1.0.0 platforms: - linux/amd64 - linux/arm64 secrets: npm_token: environment: NPM_TOKEN

#Extensions (Compose Specification)

Расширения для переиспользования конфигурации:

x-api-defaults: &api-defaults restart: unless-stopped logging: driver: json-file options: max-size: "10m" max-file: "3" networks: - backend services: api-v1: <<: *api-defaults image: myapi:v1 ports: - "8001:8000" api-v2: <<: *api-defaults image: myapi:v2 ports: - "8002:8000" networks: backend:

#Включение/выключение сервисов условно

services: debug-tools: image: busybox command: top profiles: - debug # Запускается только с --profile debug # Условное включение через переменную monitoring: image: prom/prometheus deploy: replicas: ${MONITORING_REPLICAS:-0} # При MONITORING_REPLICAS=0 сервис не запускается

#Работа с несколькими версиями образов

services: api: image: myapi:${API_VERSION:-latest} # Запуск конкретной версии # API_VERSION=v1.2.3 docker compose up -d db: image: postgres:${POSTGRES_VERSION:-15} # POSTGRES_VERSION=14-alpine docker compose up -d

#CI/CD интеграция

# docker-compose.ci.yml services: test: build: ./api environment: - CI=true - DATABASE_URL=postgresql://test:test@db:5432/test depends_on: db: condition: service_healthy command: pytest db: image: postgres:15-alpine environment: POSTGRES_USER: test POSTGRES_PASSWORD: test POSTGRES_DB: test healthcheck: test: ["CMD-SHELL", "pg_isready -U test"] interval: 5s timeout: 3s retries: 5
# .gitlab-ci.yml test: script: - docker compose -f docker-compose.yml -f docker-compose.ci.yml up --abort-on-container-exit --exit-code-from test - docker compose down -v

#Production Checklist

#Безопасность

services: api: image: myapi # Не запускать от root user: "1000:1000" # Read-only корневая ФС read_only: true # Временные ФС tmpfs: - /tmp - /run # Drop capabilities cap_drop: - ALL cap_add: - NET_BIND_SERVICE # Security options security_opt: - no-new-privileges:true # Ограничение ресурсов deploy: resources: limits: cpus: '1' memory: 512M

#Сеть

services: frontend: networks: - public api: networks: - public - private db: networks: - private # Нет доступа извне networks: public: driver: bridge private: driver: bridge internal: true # Нет доступа наружу

#Резервное копирование

services: backup: image: postgres:15 volumes: - ./backups:/backups - postgres-data:/var/lib/postgresql/data:ro environment: - PGPASSWORD=secret command: > sh -c "pg_dump -h db -U postgres myapp | gzip > /backups/backup-$$(date +%Y%m%d).sql.gz" depends_on: - db
# Автоматизация через cron 0 2 * * * cd /path/to/project && docker compose run --rm backup

#Производительность

#Оптимизация volumes

services: app: # ❌ Медленно: много мелких файлов volumes: - ./node_modules:/app/node_modules # ✅ Быстро: монтирование всего каталога volumes: - .:/app:cached # macOS - /app/node_modules

#Build cache

services: api: build: context: . cache_from: - myapi:latest - myapi:cache
# Предварительная загрузка кэша docker pull myapi:latest docker compose build

#Parallel запуск

# Параллельный запуск сервисов docker compose up -d --scale api=3 --scale worker=2 # Ограничение параллелизма docker compose up -d --parallel 2

#Интеграция с другими инструментами

#Docker Compose + Makefile

.PHONY: up down rebuild logs test up: docker compose up -d down: docker compose down -v rebuild: docker compose build --no-cache docker compose up -d --force-recreate logs: docker compose logs -f test: docker compose run --rm test pytest shell: docker compose exec api bash migrate: docker compose run --rm api python manage.py migrate backup: docker compose exec db pg_dump -U postgres myapp > backup.sql restore: docker compose exec -T db psql -U postgres myapp < backup.sql

#Docker Compose + GitHub Actions

# .github/workflows/test.yml name: Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Docker Compose run: | docker compose -f docker-compose.yml -f docker-compose.test.yml up -d - name: Run tests run: | docker compose run --rm test pytest - name: Cleanup run: | docker compose down -v

#Docker Compose Watch (v2.23+)

Автоматическая синхронизация файлов без пересборки:

services: api: build: context: . develop: watch: - action: sync path: ./src target: /app/src - action: rebuild path: requirements.txt
# Запуск с watch docker compose watch

#🧪 Лабораторные работы

#Lab 6.1: Запуск многоконтейнерного приложения

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

Задание:

  1. Создайте docker-compose.yml с WordPress и MySQL
  2. Запустите приложение
  3. Проверьте доступность WordPress
  4. Остановите приложение
# Создание структуры mkdir wordpress-compose && cd wordpress-compose # Создание docker-compose.yml cat > docker-compose.yml << 'EOF' version: '3.8' services: db: image: mysql:8.0 environment: MYSQL_DATABASE: wordpress MYSQL_USER: wpuser MYSQL_PASSWORD: wppass MYSQL_ROOT_PASSWORD: rootpass volumes: - wordpress-db-data:/var/lib/mysql networks: - backend wordpress: image: wordpress:latest environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: wpuser WORDPRESS_DB_PASSWORD: wppass WORDPRESS_DB_NAME: wordpress ports: - "8080:80" depends_on: - db networks: - frontend - backend volumes: wordpress-db-data: networks: frontend: backend: internal: true EOF # Запуск docker compose up -d # Проверка статуса docker compose ps # Проверка логов docker compose logs -f wordpress # Откройте http://localhost:8080 в браузере # Остановка docker compose down

Ожидаемый результат: WordPress доступен по адресу http://localhost:8080.


#Lab 6.2: Multiple Compose файлы для разных окружений

Цель: Научиться использовать несколько Compose файлов для dev/prod.

Задание:

  1. Создайте базовый docker-compose.yml
  2. Создайте docker-compose.dev.yml с volumes для разработки
  3. Запустите с переопределением для dev
# Базовая конфигурация cat > docker-compose.yml << 'EOF' version: '3.8' services: app: image: nginx:alpine ports: - "8080:80" environment: - ENV=${ENV:-development} EOF # Dev переопределение cat > docker-compose.dev.yml << 'EOF' version: '3.8' services: app: volumes: - ./html:/usr/share/nginx/html:ro environment: - DEBUG=true - ENV=development EOF # Production переопределение cat > docker-compose.prod.yml << 'EOF' version: '3.8' services: app: deploy: resources: limits: cpus: '0.5' memory: 128M environment: - ENV=production EOF # Создание тестовой страницы mkdir -p html echo "<h1>Dev Mode</h1>" > html/index.html # Запуск в dev режиме docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d # Проверка docker compose exec app env | grep -E "DEBUG|ENV" curl http://localhost:8080 # Остановка docker compose -f docker-compose.yml -f docker-compose.dev.yml down

Ожидаемый результат: Приложение запускается с разными конфигурациями в зависимости от файлов.


#Lab 6.3: Health checks с condition

Цель: Научиться использовать health checks для ожидания готовности сервисов.

Задание:

  1. Создайте compose с API и PostgreSQL
  2. Добавьте health check для БД
  3. Настройте depends_on с condition: service_healthy
  4. Проверьте порядок запуска
cat > docker-compose.yml << 'EOF' version: '3.8' services: db: image: postgres:15-alpine environment: POSTGRES_USER: test POSTGRES_PASSWORD: test POSTGRES_DB: testdb healthcheck: test: ["CMD-SHELL", "pg_isready -U test -d testdb"] interval: 5s timeout: 3s retries: 5 start_period: 10s networks: - backend api: image: python:3.11-alpine depends_on: db: condition: service_healthy environment: DATABASE_URL: postgresql://test:test@db:5432/testdb command: > sh -c "pip install psycopg2-binary && python -c \" import psycopg2 import time for i in range(10): try: conn = psycopg2.connect('dbname=testdb user=test password=test host=db') print('Connected to DB!') conn.close() break except Exception as e: print(f'Waiting for DB... {i}') time.sleep(2) \"" networks: - backend networks: backend: EOF # Запуск docker compose up # Наблюдайте за логами — API ждёт готовности БД

Ожидаемый результат: API запускается только после того, как PostgreSQL становится healthy.


#Lab 6.4: Профили в Docker Compose

Цель: Научиться использовать профили для разных сценариев.

Задание:

  1. Создайте compose с профилями для dev и test
  2. Запустите с разными профилями
  3. Проверьте, какие сервисы запустились
cat > docker-compose.yml << 'EOF' version: '3.8' services: api: image: nginx:alpine ports: - "8080:80" # Сервис только для разработки mailhog: image: mailhog/mailhog profiles: - dev ports: - "8025:8025" # Сервис для тестирования test-runner: image: alpine profiles: - test command: echo "Running tests..." # Сервис для мониторинга prometheus: image: prom/prometheus:latest profiles: - monitoring ports: - "9090:9090" volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml EOF # Создание минимального конфига Prometheus cat > prometheus.yml << 'EOF' global: scrape_interval: 15s scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] EOF # Запуск базового (только api) docker compose up -d docker compose ps # Запуск с dev профилем docker compose --profile dev up -d docker compose ps # api + mailhog # Запуск с test профилем docker compose --profile test up -d docker compose logs test-runner # Запуск с monitoring профилем docker compose --profile monitoring up -d docker compose ps # api + prometheus # Остановка docker compose --profile dev --profile test --profile monitoring down

Ожидаемый результат: Разные профили запускают разные наборы сервисов.


#Lab 6.5: Бэкап базы данных из Docker Compose

Цель: Научиться создавать бэкапы базы данных из запущенного Compose приложения.

Задание:

  1. Запустите WordPress с MySQL
  2. Добавьте данные в базу
  3. Создайте бэкап через docker compose exec
  4. Восстановите из бэкапа
# Запуск WordPress (из Lab 6.1) docker compose up -d # Добавление данных docker compose exec db mysql -u root -prootpass -e \ "CREATE TABLE backup_test (id INT, data VARCHAR(100));" docker compose exec db mysql -u root -prootpass -e \ "INSERT INTO backup_test VALUES (1, 'Important data');" # Создание бэкапа docker compose exec db mysqldump -u root -prootpass wordpress > backup.sql # Проверка бэкапа cat backup.sql | grep backup_test # Удаление данных docker compose exec db mysql -u root -prootpass -e "DROP TABLE backup_test;" # Восстановление docker compose exec -T db mysql -u root -prootpass wordpress < backup.sql # Проверка восстановления docker compose exec db mysql -u root -prootpass -e "SELECT * FROM backup_test;" # Остановка docker compose down rm backup.sql

Ожидаемый результат: Данные успешно восстанавливаются из бэкапа.


#Lab 6.6: Docker Compose Watch для разработки

Цель: Научиться использовать Watch режим для автоматической синхронизации кода.

Задание:

  1. Создайте простое API приложение
  2. Настройте Docker Compose Watch
  3. Проверьте автоматическую синхронизацию изменений
# Создание структуры mkdir watch-demo && cd watch-demo # Простое Flask приложение cat > app.py << 'EOF' from flask import Flask import os app = Flask(__name__) @app.route('/') def hello(): return f"<h1>Hello from Watch Demo!</h1><p>Version: {os.getenv('VERSION', 'dev')}</p>" if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) EOF cat > requirements.txt << 'EOF' flask==3.0.0 EOF cat > Dockerfile << 'EOF' FROM python:3.11-alpine WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["python", "app.py"] EOF # docker-compose.yml с Watch cat > docker-compose.yml << 'EOF' services: api: build: context: . develop: watch: - action: sync path: ./app.py target: /app/app.py - action: rebuild path: requirements.txt ports: - "5000:5000" environment: - VERSION=1.0.0 EOF # Запуск в режиме watch docker compose watch # В другом терминале измените app.py echo "Version: 2.0.0" >> app.py # Изменения автоматически синхронизируются curl http://localhost:5000

Ожидаемый результат: Изменения в коде автоматически применяются без пересборки.


#Lab 6.7: Production конфигурация с security hardening

Цель: Научиться настраивать безопасную production конфигурацию.

Задание:

  1. Создайте production конфигурацию с ограничениями безопасности
  2. Настройте read-only файловую систему
  3. Ограничьте ресурсы и capabilities
mkdir prod-secure && cd prod-secure cat > docker-compose.yml << 'EOF' services: api: image: nginx:alpine ports: - "8080:80" # Не root пользователь user: "101:101" # Read-only корневая ФС read_only: true # Временные директории tmpfs: - /tmp:size=64M - /var/cache/nginx:size=64M - /var/run:size=16M # Drop всех capabilities cap_drop: - ALL cap_add: - NET_BIND_SERVICE # Security options security_opt: - no-new-privileges:true # Ограничение ресурсов deploy: resources: limits: cpus: '0.5' memory: 128M reservations: cpus: '0.25' memory: 64M # Логирование с ротацией logging: driver: json-file options: max-size: "10m" max-file: "3" compress: "true" # Health check healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost/health"] interval: 30s timeout: 10s retries: 3 start_period: 10s # Restart policy restart: unless-stopped networks: default: driver: bridge EOF # Запуск docker compose up -d # Проверка безопасности docker compose exec api whoami docker compose exec api touch /test # Должно fail с read-only FS # Проверка ограничений docker compose top docker stats # Остановка docker compose down

Ожидаемый результат: Контейнер запускается с ограниченными правами и read-only ФС.


#Lab 6.8: Extensions и переиспользование конфигурации

Цель: Научиться использовать YAML extensions для DRY конфигурации.

Задание:

  1. Создайте конфигурацию с переиспользуемыми блоками
  2. Используйте anchors и aliases
  3. Запустите несколько версий API
mkdir extensions-demo && cd extensions-demo cat > docker-compose.yml << 'EOF' # Переиспользуемые блоки x-api-defaults: &api-defaults restart: unless-stopped logging: driver: json-file options: max-size: "10m" max-file: "3" networks: - backend healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 x-logging: &logging-json driver: json-file options: max-size: "10m" max-file: "3" services: api-v1: <<: *api-defaults image: myapi:v1 ports: - "8001:8000" environment: - VERSION=v1 - LOG_LEVEL=info api-v2: <<: *api-defaults image: myapi:v2 ports: - "8002:8000" environment: - VERSION=v2 - LOG_LEVEL=debug logging: <<: *logging-json api-v3: <<: *api-defaults image: myapi:v3 ports: - "8003:8000" environment: - VERSION=v3 - LOG_LEVEL=warning # Load balancer nginx: image: nginx:alpine ports: - "80:80" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro depends_on: - api-v1 - api-v2 - api-v3 networks: - backend networks: backend: driver: bridge EOF cat > nginx.conf << 'EOF' events { worker_connections 1024; } http { upstream api { least_conn; server api-v1:8000 weight=1; server api-v2:8000 weight=2; server api-v3:8000 weight=3; } server { listen 80; location / { proxy_pass http://api; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /health { return 200 "OK"; } } } EOF # Запуск docker compose up -d # Проверка load balancing for i in {1..10}; do curl -s http://localhost/ | grep VERSION; done # Остановка docker compose down

Ожидаемый результат: Несколько версий API работают с переиспользуемой конфигурацией.


#Lab 6.9: CI/CD пайплайн с Docker Compose

Цель: Научиться использовать Docker Compose в CI/CD пайплайнах.

Задание:

  1. Создайте конфигурацию для тестирования
  2. Настройте запуск тестов в CI
  3. Проверьте exit code тестов
mkdir ci-demo && cd ci-demo # Простое приложение с тестами cat > app.py << 'EOF' def add(a, b): return a + b def subtract(a, b): return a - b EOF cat > test_app.py << 'EOF' from app import add, subtract def test_add(): assert add(2, 3) == 5 assert add(-1, 1) == 0 def test_subtract(): assert subtract(5, 3) == 2 assert subtract(10, 7) == 3 if __name__ == "__main__": test_add() test_subtract() print("All tests passed!") EOF cat > Dockerfile << 'EOF' FROM python:3.11-alpine WORKDIR /app COPY . . CMD ["python", "test_app.py"] EOF # Базовая конфигурация cat > docker-compose.yml << 'EOF' services: app: build: . EOF # CI конфигурация cat > docker-compose.ci.yml << 'EOF' services: test: build: . environment: - CI=true - PYTHONDONTWRITEBYTECODE=1 command: python test_app.py EOF # Запуск тестов docker compose -f docker-compose.yml -f docker-compose.ci.yml run --rm test # Проверка exit code echo "Exit code: $?" # Остановка docker compose down

Ожидаемый результат: Тесты запускаются и возвращают корректный exit code.


#Lab 6.10: Multi-platform сборка

Цель: Научиться собирать образы для нескольких архитектур.

Задание:

  1. Настройте buildx для multi-platform сборки
  2. Соберите образ для amd64 и arm64
  3. Проверьте поддержку архитектур
mkdir multiarch-demo && cd multiarch-demo cat > Dockerfile << 'EOF' FROM --platform=$TARGETPLATFORM python:3.11-alpine WORKDIR /app RUN uname -m > /app/arch.txt CMD ["cat", "/app/arch.txt"] EOF cat > docker-compose.yml << 'EOF' services: arch-test: build: context: . platforms: - linux/amd64 - linux/arm64 EOF # Создание buildx builder docker buildx create --use --name multiarch-builder # Сборка для нескольких платформ docker compose build # Проверка образов docker buildx imagetools inspect $(docker compose images -q) # Запуск для разных платформ docker compose run --platform linux/amd64 arch-test docker compose run --platform linux/arm64 arch-test # Остановка docker compose down docker buildx rm multiarch-builder

Ожидаемый результат: Образ собирается и запускается на разных архитектурах.


#Чеклист выполнения лабораторных

  • Lab 6.1: WordPress доступен по порту 8080
  • Lab 6.2: Multiple compose файлы работают для dev/prod
  • Lab 6.3: API ждёт готовности БД через health check
  • Lab 6.4: Профили запускают разные сервисы
  • Lab 6.5: Бэкап создан и данные восстановлены
  • Lab 6.6: Watch режим синхронизирует изменения
  • Lab 6.7: Production конфигурация с security hardening
  • Lab 6.8: Extensions для DRY конфигурации
  • Lab 6.9: CI/CD пайплайн с Docker Compose
  • Lab 6.10: Multi-platform сборка работает

#Шпаргалка: Быстрый старт

#Минимальный docker-compose.yml

services: app: image: nginx ports: - "80:80"

#Типичный development setup

services: app: build: . ports: - "8000:8000" volumes: - ./src:/app/src environment: - DEBUG=true depends_on: db: condition: service_healthy db: image: postgres:15 environment: POSTGRES_PASSWORD: secret volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 volumes: pgdata:

#Production checklist

services: app: image: myapp:v1.0.0 # Конкретная версия restart: unless-stopped user: "1000:1000" # Не root read_only: true # Read-only FS tmpfs: - /tmp cap_drop: - ALL security_opt: - no-new-privileges:true deploy: resources: limits: cpus: '1' memory: 512M logging: driver: json-file options: max-size: "10m" max-file: "3" healthcheck: test: ["CMD", "curl", "-f", "http://localhost/health"] interval: 30s timeout: 10s retries: 3 secrets: - db_password secrets: db_password: external: true

#Частые ошибки и решения

ОшибкаПричинаРешение
port is already allocatedПорт занят другим процессомИзмените порт в ports: или освободите порт
service_healthy never reachedНеправильный health checkПроверьте команду health check и таймауты
cannot access volumeVolume не созданДобавьте volume в секцию volumes:
service not foundСервис не в той сетиДобавьте сервисы в общую сеть
permission deniedНеправильный пользовательИспользуйте user: или исправьте права на volume
build failed: not foundФайл не в контекстеПроверьте context: и пути в Dockerfile
env variable not setПеременная не загруженаПроверьте .env файл или env_file:

#Полезные команды

# Валидация конфигурации docker compose config # Визуализация зависимостей docker compose config --services --depends-on # Конвертация в JSON docker compose config --format json # Запуск одноразовой команды docker compose run --rm service command # Копирование файлов docker compose cp service:/path/file.txt ./local/ # Пауза/возобновление сервисов docker compose pause docker compose unpause # Масштабирование docker compose up -d --scale api=3 # Принудительная пересборка docker compose up -d --build --force-recreate # Полная очистка docker compose down -v --rmi all --remove-orphans

#Ресурсы

  • Официальная документация
  • Compose Specification
  • Docker Compose GitHub
  • Awesome Compose — готовые примеры

Далее: Многоэтапная сборка