До основного вмісту

Traefik: reverse proxy з автоматичним TLS для Docker

Хмара та DevOps · · 5 хв читання
Ілюстрація до статті «Traefik: reverse proxy з автоматичним TLS для Docker»

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 автоматично при першому запиті.

КритерійTraefikCaddy
Виявлення сервісівАвтоматично через 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 щоразу перетворюється на помітну рутину.

Чи була стаття корисною?
← Назад до бази знань Поставити питання підтримці