Traefik — reverse proxy, который сам находит контейнеры Docker и сам выпускает TLS-сертификаты, без ручной правки конфигов при каждом новом сайте. Вместо статичного файла с блоками server, как у nginx, Traefik читает labels прямо на контейнерах и перестраивает маршруты на лету. Разберём установку в Docker Compose, автоматический TLS через Let's Encrypt и типичные ошибки.
Что такое Traefik и чем он отличается от nginx
nginx требует отдельного конфиг-файла на каждый сайт и перезагрузки процесса при изменениях. Traefik подключается к Docker через сокет, видит все запущенные контейнеры и строит маршруты из их labels автоматически — без reload и без отдельных файлов конфигурации на каждый домен. Новый сайт добавляется одной строкой labels в docker-compose.yml, а не отдельным конфигом reverse proxy.
Обратная сторона: Traefik добавляет ещё один слой абстракции поверх привычного HTTP-сервера, и отладку маршрутов приходится вести через его собственный дашборд, а не через привычные логи nginx.
Установка Traefik в Docker Compose
Базовый сервис Traefik в docker-compose.yml с включённым Docker-провайдером:
services:
traefik:
image: traefik:v3.1
command:
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
restart: unless-stopped
Флаг exposedbydefault=false обязателен: без него Traefik открывает наружу вообще все контейнеры на сервере, а не только те, что явно помечены labels.
Автоматический TLS через Let's Encrypt
Traefik сам запрашивает и продлевает сертификаты через протокол ACME, без cron-задачи и отдельного certbot. Для этого в команду сервиса добавляют resolver:
command:
- --certificatesresolvers.le.acme.email=admin@example.com
- --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
- --certificatesresolvers.le.acme.httpchallenge.entrypoint=web
Файл acme.json обязан иметь права 600 — Let's Encrypt хранит в нём приватные ключи сертификатов, и при более открытых правах Traefik откажется его использовать.
Как Traefik находит контейнеры: labels на сервисах
Каждый контейнер, который должен получить маршрут, помечается labels прямо в описании сервиса:
services:
app:
image: myapp:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`app.example.com`)"
- "traefik.http.routers.app.entrypoints=websecure"
- "traefik.http.routers.app.tls.certresolver=le"
- "traefik.http.services.app.loadbalancer.server.port=8080"
Traefik сам подхватывает контейнер после docker compose up -d: не нужно отдельно редактировать конфиг proxy и перезапускать его.
Несколько сайтов на одном сервере
Маршрутизация по доменам держится на правиле Host() в labels: разные контейнеры отвечают на разные домены через один и тот же порт 443 сервиса Traefik. Для каждого домена задаётся свой certresolver, и Traefik выпускает отдельный сертификат на каждый Host автоматически при первом запросе.
| Критерий | Traefik | Caddy |
|---|---|---|
| Обнаружение сервисов | Автоматически через Docker labels | Через статичный Caddyfile |
| Автоматический TLS | Да, через ACME resolver | Да, из коробки для любого домена |
| Перезагрузка при новом сайте | Не требуется | Требуется reload конфига |
Дашборд и наблюдение за маршрутами
Встроенный дашборд на порту 8080 показывает список роутеров, сервисов и middleware в реальном времени — удобно проверить, что labels распознаны правильно. В продакшене дашборд закрывают тем же механизмом labels с basic-auth middleware, а не оставляют открытым наружу.
- Включить дашборд флагом
--api.dashboard=trueтолько на этапе отладки - Закрыть путь
/dashboard/отдельным роутером с middleware авторизации - Смотреть логи access через
--accesslog=trueпри разборе проблем с маршрутизацией
Частые ошибки конфигурации
Первая ошибка — забытый exposedbydefault=false, из-за чего наружу открываются служебные контейнеры вроде баз данных. Вторая — неправильные права на acme.json, из-за которых Traefik тихо не может сохранить сертификат и перевыпускает его при каждом рестарте, упираясь в лимиты Let's Encrypt. Третья — отсутствие traefik.enable=true на нужном контейнере, из-за чего сервис остаётся недоступным, хотя все остальные labels выставлены верно.
Если сайтов на сервере много и нужен кластер из нескольких VDS, тот же Traefik работает и поверх Docker Swarm, читая labels уже из режима stack. Для сравнения с более простым по конфигурации reverse proxy смотрите статью про Caddy Server. Если инфраструктура уже перешла на полноценный Kubernetes, аналогичную роль там выполняет ingress-nginx.
Итог: чек-лист запуска Traefik
Traefik избавляет от ручного редактирования конфигов reverse proxy при каждом новом контейнере, если labels настроены аккуратно с самого начала.
- Флаг
exposedbydefault=falseв конфигурации Docker-провайдера - Права 600 на файл
acme.jsonс сертификатами traefik.enable=trueявно на каждом контейнере, который должен быть виден снаружи- Дашборд закрыт middleware авторизации, а не открыт на весь интернет
Частые вопросы
Можно ли через Traefik проксировать трафик не на Docker-контейнер, а на внешний сервер или IP-адрес?
Механизм labels, описанный в статье, рассчитан именно на контейнеры Docker, которые Traefik видит через сокет сам. Для маршрутизации на внешний сервер или адрес вне Docker нужен отдельный провайдер статической конфигурации, а не labels на контейнере — настройка в этом случае получается более ручной и не такой автоматической, как для локальных сервисов.
Контейнер запущен с верными labels, но снаружи всё равно недоступен — в чём может быть причина?
Чаще всего не хватает одной строки в labels, которая явно разрешает Traefik видеть именно этот контейнер — без неё сервис остаётся невидимым, даже если остальные правила маршрутизации описаны верно. Стоит также проверить, что флаг, ограничивающий автоматический показ контейнеров наружу, не блокирует конкретно этот сервис по умолчанию.
Нужно ли вручную продлевать сертификаты Let's Encrypt, выпущенные через Traefik?
Нет, именно в этом и состоит удобство встроенного ACME resolver'а: Traefik сам следит за сроком действия сертификата и запрашивает новый заблаговременно, без отдельного cron-задания и без участия человека. Единственное условие — файл, где хранятся сертификаты, должен сохранять верные права доступа, иначе Traefik не сможет записать туда обновлённые данные при продлении.
Стоит ли переходить на Traefik, если на сервере уже работает nginx и сайтов немного?
Если сайтов мало и конфиги почти не меняются, выгода от автоматического обнаружения контейнеров невелика, а разбираться с ещё одним слоем абстракции и отдельным дашбордом вместо привычных логов nginx — лишние усилия. Переход оправдан, когда новые сайты и контейнеры появляются часто и ручная правка конфига reverse proxy каждый раз становится заметной рутиной.