Руководство по Docker Compose: Управление многоконтейнерными приложениями
Многоконтейнерные приложения с Docker Compose: зависимости сервисов, переменные окружения, health check, масштабирование и запуск в production.
Установка Traefik: обнаружение сервисов через Docker-провайдер, SSL от Let's Encrypt, middleware, dashboard, Kubernetes Ingress и балансировка нагрузки.
Traefik — современный edge router и обратный прокси, разработанный для микросервисных архитектур. Благодаря глубокой интеграции с Docker и Kubernetes он автоматически обнаруживает и маршрутизирует сервисы.
Ключевые особенности Traefik:
Traefik v3 предлагает лучшую производительность и новые функции по сравнению с v2. Это руководство сосредоточено на Traefik v3.
# docker-compose.yml
services:
traefik:
image: traefik:v3.0
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "8080:8080" # Dashboard (закрыть в production)
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- ./config:/etc/traefik/config:ro
- traefik_certs:/certs
networks:
- traefik-net
labels:
- "traefik.enable=true"
# Dashboard
- "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$xyz$$hash"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
volumes:
traefik_certs:
networks:
traefik-net:
external: true
# traefik.yml
global:
checkNewVersion: true
sendAnonymousUsage: false
api:
dashboard: true
insecure: false # false в production
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
websecure:
address: ":443"
http:
tls:
certResolver: letsencrypt
http3:
advertisedPort: 443
certificatesResolvers:
letsencrypt:
acme:
email: admin@example.com
storage: /certs/acme.json
httpChallenge:
entryPoint: web
# DNS-challenge (для wildcard)
# dnsChallenge:
# provider: cloudflare
# resolvers:
# - "1.1.1.1:53"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: traefik-net
file:
directory: /etc/traefik/config
watch: true
log:
level: INFO
filePath: /var/log/traefik/traefik.log
accessLog:
filePath: /var/log/traefik/access.log
bufferingSize: 100
Автоматически регистрируйте сервисы в Traefik с помощью меток Docker:
# Пример приложения
services:
webapp:
image: nginx:alpine
networks:
- traefik-net
labels:
# Включить Traefik
- "traefik.enable=true"
# HTTP-роутер
- "traefik.http.routers.webapp.rule=Host(`app.example.com`)"
- "traefik.http.routers.webapp.entrypoints=websecure"
- "traefik.http.routers.webapp.tls.certresolver=letsencrypt"
# Порт сервиса
- "traefik.http.services.webapp.loadbalancer.server.port=80"
# Применить middleware
- "traefik.http.routers.webapp.middlewares=security-headers,rate-limit"
networks:
traefik-net:
external: true
services:
api:
image: myapi:latest
networks:
- traefik-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.example.com`)"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
- "traefik.http.services.api.loadbalancer.server.port=3000"
# Проверка работоспособности
- "traefik.http.services.api.loadbalancer.healthcheck.path=/health"
- "traefik.http.services.api.loadbalancer.healthcheck.interval=30s"
frontend:
image: myfrontend:latest
networks:
- traefik-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host(`example.com`) || Host(`www.example.com`)"
- "traefik.http.routers.frontend.entrypoints=websecure"
- "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
- "traefik.http.services.frontend.loadbalancer.server.port=80"
networks:
traefik-net:
external: true
# config/middlewares.yml
http:
middlewares:
# Заголовки безопасности
security-headers:
headers:
stsSeconds: 31536000
stsIncludeSubdomains: true
stsPreload: true
forceSTSHeader: true
contentTypeNosniff: true
frameDeny: true
referrerPolicy: "strict-origin-when-cross-origin"
customResponseHeaders:
X-Powered-By: ""
Server: ""
# Ограничение скорости
rate-limit:
rateLimit:
average: 100
burst: 50
period: 1m
sourceCriterion:
ipStrategy:
depth: 1
# Basic auth
basic-auth:
basicAuth:
users:
- "admin:$apr1$xyz$hashedpassword"
removeHeader: true
# Белый список IP
ip-whitelist:
ipAllowList:
sourceRange:
- "192.168.1.0/24"
- "10.0.0.0/8"
# Перенаправление www на non-www
www-redirect:
redirectRegex:
regex: "^https://www\\.(.*)"
replacement: "https://${1}"
permanent: true
# Безопасная конфигурация dashboard
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik-dashboard.rule=Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
- "traefik.http.routers.traefik-dashboard.service=api@internal"
- "traefik.http.routers.traefik-dashboard.entrypoints=websecure"
- "traefik.http.routers.traefik-dashboard.tls.certresolver=letsencrypt"
- "traefik.http.routers.traefik-dashboard.middlewares=dashboard-auth"
- "traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$apr1$$xyz$$hash"
Генерация пароля basic auth:
# Генерация пароля с htpasswd
echo $(htpasswd -nB admin) | sed -e s/\\$/\\$\\$/g
# Или с openssl
echo "admin:$(openssl passwd -apr1 'вашпароль')" | sed -e 's/\$/\$\$/g'
# Добавить Helm-репозиторий Traefik
helm repo add traefik https://traefik.github.io/charts
helm repo update
# Установить Traefik
helm install traefik traefik/traefik \
--namespace traefik \
--create-namespace \
--set deployment.replicas=2 \
--set ports.web.redirectTo.port=websecure \
--set ingressRoute.dashboard.enabled=true
# ingressroute.yml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: webapp-ingress
namespace: default
spec:
entryPoints:
- websecure
routes:
- match: Host(`app.example.com`)
kind: Rule
services:
- name: webapp-service
port: 80
middlewares:
- name: security-headers
tls:
certResolver: letsencrypt
# middleware.yml
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: security-headers
namespace: default
spec:
headers:
stsSeconds: 31536000
stsIncludeSubdomains: true
contentTypeNosniff: true
frameDeny: true
# traefik.yml - TCP-точка входа
entryPoints:
mysql:
address: ":3306"
redis:
address: ":6379"
# config/tcp.yml
tcp:
routers:
mysql-router:
entryPoints:
- mysql
rule: "HostSNI(`*`)"
service: mysql-service
services:
mysql-service:
loadBalancer:
servers:
- address: "mysql:3306"
# Балансировка нагрузки с несколькими экземплярами
services:
api:
image: myapi:latest
deploy:
replicas: 3
networks:
- traefik-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.example.com`)"
- "traefik.http.services.api.loadbalancer.server.port=3000"
# Sticky sessions
- "traefik.http.services.api.loadbalancer.sticky.cookie=true"
- "traefik.http.services.api.loadbalancer.sticky.cookie.name=traefik_session"
- "traefik.http.services.api.loadbalancer.sticky.cookie.secure=true"
# Проверка работоспособности
- "traefik.http.services.api.loadbalancer.healthcheck.path=/health"
- "traefik.http.services.api.loadbalancer.healthcheck.interval=10s"
- "traefik.http.services.api.loadbalancer.healthcheck.timeout=3s"
Traefik — мощное решение обратного прокси и балансировщика нагрузки для современных микросервисных инфраструктур. Благодаря глубокой интеграции с Docker и Kubernetes, автоматическому управлению SSL и богатой экосистеме middleware, это надёжный выбор для production-окружений. Конфигурация на основе меток позволяет каждому сервису определять собственные правила маршрутизации.
Traefik имеет глубокую интеграцию с Docker/Kubernetes и автоматически обнаруживает сервисы. Nginx требует статической конфигурации и перезагрузки при каждом изменении. Traefik поддерживает динамическую конфигурацию и обновляется без простоя. Nginx более зрелый и может показывать лучшую производительность при очень высоком трафике. Traefik предпочтителен для микросервисных окружений, Nginx — для традиционных веб-серверов.
Никогда не открывайте dashboard в небезопасном режиме (порт 8080) в production. Защитите dashboard с помощью HTTPS и basic auth, добавив метки к контейнеру Traefik. Ограничьте доступ определёнными IP с помощью middleware белого списка IP. Альтернативно можно полностью отключить dashboard и использовать Prometheus/Grafana для мониторинга.
Установите провайдер dnsChallenge в разделе certificatesResolvers в traefik.yml. Для Cloudflare требуются 'provider: cloudflare' и переменная окружения 'CF_DNS_API_TOKEN'. Определите соответствующие API-ключи как переменные окружения для других DNS-провайдеров. DNS-challenge безопаснее HTTP-challenge и позволяет выпускать wildcard-сертификаты.
Да, middleware применяются в порядке их определения. Обычно рекомендуемый порядок: белый список IP → ограничение скорости → аутентификация → заголовки. Неправильный порядок может привести к неожиданному поведению. Например, если поставить middleware аутентификации перед ограничением скорости, неаутентифицированные запросы тоже будут учитываться в лимите.
Используйте rolling updates в Docker Swarm или Kubernetes. Traefik автоматически направляет трафик, когда новые контейнеры готовы. Конфигурация проверки работоспособности критически важна: трафик не отправляется на нездоровые контейнеры. Определите endpoint проверки работоспособности с меткой 'traefik.http.services.myapp.loadbalancer.healthcheck.path=/health'.
Traefik получает отдельные сертификаты для каждого домена. Для нескольких доменов используйте 'Host(`a.com`) || Host(`b.com`)' в правиле роутера. Отдельные сертификаты автоматически выпускаются для каждого домена. DNS-challenge необходим для wildcard-сертификатов. Для SAN-сертификатов может потребоваться ручная настройка или использование внешних сертификатов.
Многоконтейнерные приложения с Docker Compose: зависимости сервисов, переменные окружения, health check, масштабирование и запуск в production.
CI/CD с GitHub Actions: сборка и публикация Docker-образов, развёртывание на сервер по SSH, автотесты, управление секретами и оптимизация workflow.
Ansible по шагам: установка, инвентарь, написание playbook, роли, переменные, зашифрованный vault, ad-hoc команды и автоматизация настройки серверов.