SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor

Миграция Traefik с v2 на v3: что перестанет работать

При обновлении до Traefik v3 сервис не запустится с параметрами swarmMode или pilot в static конфигурации. Узнайте, как исправить ошибку конфигурации и обновить правила.

Что изменилось между Traefik v2 и v3

Миграция с Traefik v2 на v3 в основном сводится к переименованию параметров. Самое известное изменение — middleware ipWhiteList теперь называется ipAllowList. Помимо этого, в v3 ужесточен синтаксис правил маршрутизации (PathPrefix больше не поддерживает регулярные выражения, некоторые матчеры были переименованы или удалены), полностью исключены некоторые провайдеры и опции. Остальные компоненты продолжают работать: entrypoints, настройка сертификатов ACME, рабочий процесс с Docker labels и ваш acme.json переносятся без изменений. В v3 также предусмотрен режим совместимости, который позволяет использовать синтаксис правил v2. Это дает возможность сначала обновить бинарный файл, а затем переписывать правила для каждого сервиса по очереди, вместо того чтобы выполнять рискованное обновление за один вечер.

В этом руководстве предполагается использование Docker Compose с метками (labels), как описано в руководстве по reverse proxy Traefik. Эта страница уже адаптирована под v3; данное руководство предназначено для серверов, где всё ещё используется тег traefik:v2.

Переименования и удаления

  • ipWhiteList теперь называется ipAllowList, это касается как HTTP, так и TCP middleware. Опции внутри остались прежними, поэтому sourcerange сохраняет свой точный смысл. Текущие релизы v3, включая v3.7, всё ещё принимают старое имя как устаревший псевдоним и продолжают применять список, записывая в лог предупреждение об устаревании, поэтому данное переименование не приводит к сбоям. Тем не менее, выполните переименование: старое имя считается устаревшим, а v2.11 уже понимает ipAllowList, так что переименование можно применить до обновления.
  • providers.docker.swarmMode=true удалён. У Swarm теперь свой провайдер, который настраивается как providers.swarm.endpoint.
  • Секция pilot удалена полностью.
  • experimental.http3 удалён. HTTP/3 теперь включается непосредственно в entrypoint.
  • tls.caOptional удалён из провайдеров и из middleware forwardAuth. Если этот middleware стоит перед самостоятельно размещенным Authentik SSO, удаление строки caOptional — это вся миграция, так как адрес forwardAuth, доверенные заголовки и outpost за ними ведут себя в v3 точно так же.
  • Провайдер метрик InfluxDB v1, провайдер Rancher и провайдер Marathon удалены.
  • Трассировка перенесена на OpenTelemetry. Выделенные бэкенды трассировки, включая интеграции с Jaeger и Zipkin, удалены; теперь v3 экспортирует данные через OTLP (протокол OpenTelemetry).
  • Устаревшие опции ssl* внутри middleware headers (sslRedirect, sslHost и остальные) удалены. Их заменили редиректы на уровне entrypoint и middleware redirectScheme.

Эти удаления важнее, чем кажется, так как Traefik отказывается запускаться, если в его статической конфигурации есть удалённая или неизвестная опция. Оставшаяся строка pilot, swarmMode, experimental.http3 или провайдер tls.caOptional остановит контейнер при загрузке: Traefik сначала запишет в лог строку с названием лишнего параметра (например, опция провайдера Docker tls.CAOptional была удалена в v3), а затем завершится с ошибкой incompatible deprecated install configuration option found. В релизах до v3.4 это сообщение выглядит как incompatible deprecated static option found. Опция, о которой Traefik никогда не знал (например, опечатка), остановит его с ошибкой field not found и указанием узла. Очистите статическую конфигурацию перед тем, как менять тег образа.

Если middleware имеет имя, которое Traefik не знает (опечатка или имя, которое было удалено, а не заменено псевдонимом), результат будет иным: роутер, ссылающийся на него, загрузится с ошибкой вместо маршрута, дашборд пометит его, а API сообщит о middleware "offce@docker" does not exist. Запросы к этому хостнейму получат 404, так как роутер не был запущен. Обратите внимание, что ipwhitelist НЕ относится к этой категории в текущей версии v3: он существует как устаревший псевдоним, поэтому непереименованная метка продолжит работать без уведомлений.

Изменения в синтаксисе правил

Правила — это место, где происходит реальная перезапись. Изменения в v3:

  • Кавычки не изменились. Обе версии принимают значения правил в обратных кавычках или экранированных двойных кавычках и отклоняют одинарные кавычки, поэтому Host(app.example.com) и экранированная двойная кавычка Host("app.example.com") остаются валидными.
  • PathPrefix больше не понимает регулярные выражения или плейсхолдеры в стиле {id}. Правило v2, такое как PathPrefix(/api/{version:v[0-9]+}), должно стать матчером PathRegexp, написанным с использованием синтаксиса регулярных выражений Go.
  • Матчеры теперь принимают только одно значение. v2 позволял Host(app.example.com,www.example.com); v3 требует Host(app.example.com) || Host(www.example.com). Исключениями являются Header, HeaderRegexp, Query и QueryRegexp, которые по-прежнему принимают имя и значение.
  • Headers и HeadersRegexp переименованы в Header и HeaderRegexp.
  • HostHeader удален. Используйте Host, который в v3 выполняет ту же функцию.
  • Появились два новых матчера: PathRegexp и QueryRegexp. Матчер ClientIP для сопоставления адреса клиента внутри правила уже существовал в v2.11 и перенесен без изменений.

Хорошая новость: простое правило Host(app.example.com), написанное с использованием обратных кавычек, уже является валидным синтаксисом v3. Большинство небольших конфигураций Compose используют именно такой формат, а значит, большинство меток мигрируют без правок правил.

Проверка меток перед началом работы

Вы можете оценить масштаб миграции с помощью одного поиска, так как каждое критическое изменение меток оставляет шаблон, который можно найти через grep:

grep -rnE 'ipwhitelist|HostHeader|Headers\(|PathPrefix\(`[^`]*\{|Host\(`[^`]*`,' docker-compose*.yml

Каждое совпадение — это строка, которую нужно отредактировать. ipwhitelist превращается в ipallowlist. HostHeader превращается в Host. Headers превращается в Header. Заполнитель {...} внутри PathPrefix становится сопоставителем PathRegexp. Запятая внутри Host() превращается в два сопоставителя Host(), объединенных через ||. Отсутствие совпадений означает, что ваши метки уже соответствуют синтаксису v3, и миграция сводится к статической конфигурации и тегу образа. Если экран заполнен результатами поиска, самое время задаться вопросом, является ли этот прокси по-прежнему оптимальным выбором для вашего сервера, а сравнение Traefik с Nginx и Caddy поможет сопоставить затраты на переписывание конфигурации с требованиями других решений для каждого приложения.

Что остаётся неизменным

Точки входа (entrypoints) и их перенаправление с HTTP на HTTPS, ACME-резолверы с обоими типами проверок (challenge), exposedByDefault, метки маршрутизатора и сервисов, loadbalancer.server.port, а также панель управления (dashboard) работают в v3 так же, как и в v2. Ваши сертификаты также сохраняют работоспособность, так как v3 продолжает считывать файл acme.json, созданный в v2. В любом случае сделайте резервную копию файла перед началом работ, так как откат с его потерей приведёт к срабатыванию лимита Let's Encrypt на дублирование сертификатов:

cp ./letsencrypt/acme.json ./letsencrypt/acme.json.v2-backup

Путь миграции

Шаг 1: зафиксируйте текущую версию. Измените любой тег traefik:latest или traefik:v2 на конкретный релиз, который вы используете сейчас, например traefik:v2.11, и закоммитьте весь каталог compose в git. Любой последующий шаг можно будет отменить через checkout. Если пересоздание отдельного сервиса с помощью docker compose up -d <service> еще не доведено до автоматизма, руководство по основам Docker Compose описывает операции, на которых строится эта миграция.

Шаг 2: очистите статическую конфигурацию и включите режим совместимости. Удалите все параметры, исключенные в v3 (pilot, swarmMode, tls.caOptional, experimental.http3), затем укажите v3 интерпретировать правила как синтаксис v2 по умолчанию. В traefik.yml:

core:
  defaultRuleSyntax: v2

Или в качестве флага в списке command: для compose: --core.defaultRuleSyntax=v2. Режим совместимости распространяется только на синтаксис правил. Он не возвращает удаленные параметры и не переименовывает middleware за вас.

Шаг 3: примените переименование middleware, оставаясь на версии v2.11. Выполните поиск старых имен в ваших compose-файлах: grep -rn ipwhitelist docker-compose*.yml. Измените каждую метку ipwhitelist на ipallowlist и пересоздайте соответствующие сервисы с помощью docker compose up -d. Версия v2.11 уже содержит middleware IPAllowList, поэтому переименованные метки будут работать до перехода, а предупреждение об устаревании IPWhiteList исчезнет из логов v2. Релизы старше v2.11 не распознают новое имя, поэтому, если на шаге 1 вы зафиксировали более старую версию v2, сначала обновитесь до traefik:v2.11. (Если что-то пропустите, текущая версия v3 все еще поддерживает старое имя как устаревший псевдоним, поэтому список продолжит действовать; исправьте это в следующем проходе, а не посреди ночи.)

Шаг 4: переключите тег образа. Установите образ Traefik на текущий релиз v3, traefik:v3.7 по состоянию на 11 октября 2026 года (v3.7.14 — последний патч), затем:

docker compose up -d
docker compose logs -f traefik

Поскольку режим совместимости включен, ваши правила v2 продолжают работать, а так как переименование middleware уже было применено в v2.11, эти маршрутизаторы запустятся без ошибок. В корректном логе отсутствуют строки field not found и does not exist.

Трезво оцените окно простоя, которое открывает этот шаг. Маршрутизатор, ссылающийся на имя middleware, которое v3 не знает (из-за опечатки или удаленного параметра), будет недоступен с момента запуска нового Traefik до тех пор, пока вы не исправите его метки и не пересоздадите контейнер приложения. Если маршрут критически важен, удалите подозрительное middleware из метки middlewares этого маршрутизатора перед переключением и добавьте его обратно после, заранее решив, может ли этот маршрут прожить без него минуту в процессе перехода.

Шаг 5: мигрируйте правила сервис за сервисом. Работайте с каждым приложением по очереди: перепишите его правило на синтаксис v3, пересоздайте только этот сервис с помощью docker compose up -d app и протестируйте его перед переходом к следующему. Если для какого-то сервиса правило пока нельзя переписать, добавьте этому конкретному маршрутизатору метку-исключение traefik.http.routers.app.ruleSyntax=v2 и продолжайте работу.

Шаг 6: отключите режим совместимости. Когда все правила будут переведены на синтаксис v3, удалите defaultRuleSyntax и любые метки ruleSyntax, перезапустите Traefik и убедитесь, что все маршрутизаторы отображаются зеленым в панели управления. Не задерживайтесь в режиме совместимости: Traefik пометил оба параметра как устаревшие в v3.4 и удалит их в следующей мажорной версии, поэтому они являются лишь временным мостом, а не конечным решением.

До и после: метки одного сервиса

Ниже представлено приложение, в котором применены все основные изменения: многозначный Host, заполнитель PathPrefix и middleware ipWhiteList. Блок v2:

  app:
    image: app:1.4
    restart: unless-stopped
    networks:
      - proxy
    labels:
      - traefik.enable=true
      - traefik.http.routers.app.rule=Host(`app.example.com`,`www.example.com`) && PathPrefix(`/api/{version:v[0-9]+}`)
      - traefik.http.routers.app.entrypoints=websecure
      - traefik.http.routers.app.tls.certresolver=le
      - traefik.http.routers.app.middlewares=office
      - traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24
      - traefik.http.services.app.loadbalancer.server.port=8080

Тот же сервис, перенесенный на v3:

  app:
    image: app:1.4
    restart: unless-stopped
    networks:
      - proxy
    labels:
      - traefik.enable=true
      - traefik.http.routers.app.rule=(Host(`app.example.com`) || Host(`www.example.com`)) && PathRegexp(`^/api/v[0-9]+`)
      - traefik.http.routers.app.entrypoints=websecure
      - traefik.http.routers.app.tls.certresolver=le
      - traefik.http.routers.app.middlewares=office
      - traefik.http.middlewares.office.ipallowlist.sourcerange=10.0.0.0/24
      - traefik.http.services.app.loadbalancer.server.port=8080

Две метки изменились. Правило разделило многозначный Host на два условия сопоставления, объединенных через ||, заменило заполнитель на PathRegexp, а в метке middleware значение ipwhitelist было заменено на ipallowlist. Точка входа (entrypoint), резолвер сертификатов, связка роутера с middleware и порт сервиса остались без изменений.

Проверка каждого сервиса через панель управления

После каждого изменения открывайте страницу HTTP routers в панели управления. Все маршрутизаторы должны быть помечены зелёным цветом. Маршрутизатор с индикатором ошибки указывает на конкретную проблему: обычно это middleware, которое отсутствует под новым именем, или правило, которое v3 не может распознать. Затем проверьте работу снаружи, по одному доменному имени за раз:

curl -sI https://app.example.com/api/v1/status

Код 200 или стандартный редирект вашего приложения означают, что маршрутизация и TLS работают корректно. Код 404 от Traefik означает, что маршрутизатор не запустился; вернитесь в панель управления и ознакомьтесь с текстом ошибки. Держите docker compose logs -f traefik открытым во втором терминале во время работы, так как любая ошибка парсинга попадает туда в момент перезапуска контейнера.

Честность при откате

Сохраняйте файл compose версии v2, его статическую конфигурацию и резервную копию acme.json до тех пор, пока каждый сервис не начнет маршрутизироваться в v3 и не будет проверен в реальных условиях. Откат означает возврат к коммиту до миграции и выполнение docker compose up -d. Это должен быть весь файл целиком, а не только тег образа, так как синтаксис, предназначенный только для v3, будет некорректным в v2 точно так же, как синтаксис v2 был некорректным в v3: сопоставитель PathRegexp там не будет распознан. Переименованные метки ipallowlist работают в v2.11, но не в более старых релизах v2, которые не поддерживают новые имена. Если acme.json был утерян или поврежден в процессе, восстановите резервную копию перед запуском v2, чтобы при откате не исчерпать лимит Let's Encrypt на выпуск сертификатов при попытке перевыпустить пять штук одновременно.

FAQ

Нужно ли переписывать все правила маршрутизатора для Traefik v3?

Нет. Простое правило Host(app.example.com), записанное с использованием обратных кавычек, корректно работает в обеих версиях, что покрывает большинство конфигураций Compose. Переписывание требуется только там, где в правиле использовались функции, доступные только в v2: регулярные выражения или плейсхолдеры внутри Path и PathPrefix, несколько имен хостов внутри одного Host(), либо удаленные матчеры Headers, HeadersRegexp и HostHeader.

Что случилось с ipWhiteList в Traefik v3?

Он был переименован в ipAllowList, при этом конфигурация внутри осталась прежней, поэтому метка v2, такая как traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24, превращается в ту же строку, но с ipallowlist. Версия v2.11 уже поддерживает новое имя, поэтому вы можете переименовать его до обновления. Текущие релизы v3, включая v3.7, всё ещё принимают старое имя как устаревший псевдоним, поэтому непереименованная метка продолжает применять список разрешенных IP-адресов, выдавая лишь предупреждение в лог. Рассматривайте это как временную меру, а не повод отказаться от переименования: устаревшие имена могут быть удалены в любом релизе, а если Traefik не распознает имя middleware, маршрутизатор выдаст ошибку и ответ 404. Панель управления покажет эту ошибку, а запросы к данному имени хоста будут возвращать 404.

Может ли Traefik v3 по-прежнему читать синтаксис правил v2?

Да. Установите core.defaultRuleSyntax: v2 в статической конфигурации, чтобы сохранить синтаксис v2 в качестве стандартного на время миграции, и используйте метку ruleSyntax=v2 для отдельных маршрутов после того, как вернете стандартные настройки. Рассматривайте оба варианта как временные: Traefik пометил их как устаревшие в v3.4 и удалит в следующей мажорной версии.

Сохранятся ли мои сертификаты Let's Encrypt после обновления?

Да. Traefik v3 продолжает читать файл acme.json, созданный v2, поэтому сертификаты не перевыпускаются только из-за смены бинарного файла. В любом случае скопируйте файл в безопасное место перед началом работ, так как откат или удаление тома, в котором хранится acme.json, приведет к одновременному перевыпуску всех сертификатов, а Let's Encrypt разрешает только пять дубликатов сертификатов в неделю для одного и того же набора имен хостов.

Почему Traefik v3 не запускается после обновления?

Почти всегда это происходит из-за того, что статическая конфигурация всё ещё содержит опцию, удаленную в v3, и Traefik отказывается запускаться при наличии неизвестных ему параметров. Для известных остаточных параметров (pilot, providers.docker.swarmMode, experimental.http3 и tls.caOptional провайдеров) в логе указывается виновник, а затем выводится сообщение incompatible deprecated install configuration option found (incompatible deprecated static option found в v3.4 и более ранних версиях); для всего, о чем v3 никогда не слышал, например, при опечатке, выводится сообщение field not found с указанием узла. Удалите или замените каждый из них, затем снова запустите контейнер.