Docker Swarm

⌘K

Docker Swarm

Docker Compose — это инструмент для описания и запуска многоконтейнерных приложений с помощью единого конфигурационного файла (обычно docker-compose.yml). Он упрощает работу с сервисами, которые зависят друг от друга, например: веб-приложение, база данных, кеш и очередь сообщений.


Основная идея

Вместо того чтобы вручную запускать каждый контейнер и связывать их сетью и томами, вы описываете всю инфраструктуру приложения в YAML-файле:

  • Сервисы (services) — отдельные контейнеры с указанием образа или Dockerfile.
  • Сети (networks) — как контейнеры будут общаться друг с другом.
  • Тома (volumes) — куда сохраняются данные.
  • Переменные окружения (environment) — настройки для каждого сервиса.
  • Порты (ports) — маппинг между хостом и контейнером.

Пример конфигурации

version: "3.9"
services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      DB_HOST: db
      DB_USER: appuser
    depends_on:
      - db
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: appdb
    volumes:
      - db_data:/var/lib/postgresql/data

volumes:
  db_data:

Ключевые возможности

  1. Быстрый запуск окружений
    docker compose up -d — и всё приложение поднимается за один шаг.
  2. Локальная разработка
    Легко эмулировать продакшн-среду у каждого разработчика.
  3. Версионирование конфигурации
    Файл docker-compose.yml хранится в Git, что делает конфигурацию воспроизводимой.
  4. Изоляция окружений
    Каждое окружение (dev, test, stage) может иметь свой compose-файл или override.

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

  • Override-файлы (docker-compose.override.yml) — для настройки параметров в dev-режиме (маппинг исходников, hot-reload).
  • .env файл — вынос чувствительных данных и параметров окружения.
  • Профили (profiles) — запуск только нужных сервисов (docker compose --profile debug up).
  • Мульти-stage build в связке с Compose для оптимизации образов.
  • Поддержка нескольких файлов: docker compose -f docker-compose.yml -f docker-compose.prod.yml up

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

  • Docker Swarm — можно масштабировать сервисы на нескольких узлах с теми же конфигами.
  • CI/CD — автоматический запуск Compose-окружения для тестов.
  • Kubernetes — через утилиты типа Kompose можно конвертировать docker-compose.yml в манифесты K8s.

Безопасность и удобство

  • Не храните пароли прямо в YAML — используйте .env или секреты (docker secrets).
  • Для production лучше разделять образы и конфиги, избегая dev-инструментов в рантайме.
  • Мониторьте версии образов и регулярно пересобирайте сервисы.

Для чего это клиенту

Compose делает инфраструктуру приложения прозрачной, воспроизводимой и управляемой. Клиент или команда разработки получают среду, которую можно поднять на любом компьютере или сервере за минуты, без «сюрпризов» в настройках. Это сокращает время на развёртывание, упрощает онбординг новых сотрудников и минимизирует человеческий фактор.


Вот компактный продакшн‑шаблон docker-compose.yml с практичными настройками безопасности, логирования, healthcheck, ограничениями ресурсов и разделением конфигурации. Подойдёт как базис для большинства веб‑приложений (web + db + reverse‑proxy).

version: "3.9"

x-common-env: &common_env
  TZ: "UTC"
  APP_ENV: "production"
  # секреты/пароли — через .env или secrets, а не в YAML

x-common-deploy: &common_deploy
  restart: always
  # Ограничения ресурсов (примерные значения — подберите по нагрузке)
  deploy:
    resources:
      limits:
        cpus: "1.0"
        memory: "512M"
      reservations:
        cpus: "0.25"
        memory: "256M"

networks:
  edge:
    driver: bridge
  backend:
    driver: bridge
    internal: true   # недоступна извне хоста

volumes:
  db_data:
  caddy_data:    # для certmagic (автосертификаты)
  caddy_config:

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

services:
  reverse-proxy:
    image: caddy:2.8
    command: caddy run --config /etc/caddy/Caddyfile --adapter caddyfile
    ports:
      - "80:80"
      - "443:443"
    environment:
      <<: *common_env
    volumes:
      - ./ops/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - web
    networks:
      - edge
      - backend
    <<: *common_deploy
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://web:8080/health || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3

  web:
    build:
      context: .
      dockerfile: Dockerfile
      target: runtime     # используйте multi-stage build
    environment:
      <<: *common_env
      DATABASE_HOST: db
      DATABASE_USER: app_user
      DATABASE_PASSWORD_FILE: /run/secrets/db_password
      DATABASE_NAME: app
      # Логирование
      LOG_LEVEL: info
    secrets:
      - db_password
    expose:
      - "8080"            # видим только в сети backend
    depends_on:
      db:
        condition: service_healthy
    networks:
      - backend
    <<: *common_deploy
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
      interval: 20s
      timeout: 3s
      retries: 5

  db:
    image: postgres:16-alpine
    environment:
      <<: *common_env
      POSTGRES_DB: app
      POSTGRES_USER: app_user
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
      # Безопасные дефолты: отключите авто‑создание экстеншенов, ограничьте локали и т.п. — по нужде
    secrets:
      - db_password
    volumes:
      - db_data:/var/lib/postgresql/data
    expose:
      - "5432"            # только в backend
    networks:
      - backend
    <<: *common_deploy
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app_user -d app -h localhost"]
      interval: 15s
      timeout: 5s
      retries: 5
    # Доп. защита: read_only & tmpfs (сложно с БД, используйте на stateless-сервисах)

Файл ops/caddy/Caddyfile (пример с автоматическим TLS и проксированием)

example.com, www.example.com {
	encode zstd gzip
	log {
		output stdout
		format json
	}
	handle_path /health {
		respond 200
	}
	reverse_proxy web:8080 {
		health_uri /health
		trusted_proxies 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
	}
	# базовые заголовки безопасности
	header {
		Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
		X-Content-Type-Options "nosniff"
		Referrer-Policy "no-referrer"
		X-Frame-Options "DENY"
	}
}

Рекомендации к продакшн‑использованию

  • Секреты: храните в ./secrets/…, доступ ограничьте правами ОС. Для облака — лучше менеджер секретов (AWS/GCP/Azure).
  • .env: выносите не чувствительные параметры (порты, флаги фич). Не лепите туда пароли.
  • Образы: используйте multi‑stage builds, distroless/‑slim; запускайте процесс от непривилегированного пользователя (USER).
  • Логи: JSON‑формат; централизуйте сбор (ELK/Vector/Loki) через драйверы логирования или sidecar/агенты.
  • Здоровье: поддерживайте реальные health‑эндпойнты на web; для БД — pg_isready/mysqladmin ping.
  • Сети: внешние порты открывайте только на reverse‑proxy. Внутренние сервисы держите в internal сети.
  • Резервирование: бэкапы БД вне контейнера, регулярные тесты восстановления (backup verification).
  • Обновления: пересобирайте образы на патчи базового слоя; фиксируйте версии и используйте digest (image@sha256:…).
  • Безопасность: включайте readonly и tmpfs для stateless‑сервисов, no-new-privileges, cap_drop: ["ALL"] (где возможно).