راهنمای مهاجرت از Traefik v2 به v3 و رفع خطاهای رایج
در Traefik v3 تنظیمات swarmMode و pilot در فایل static حذف شدهاند. با رفع خطای incompatible deprecated install configuration option و اصلاح قوانین، سرویس خود را ارتقا دهید.
تغییرات میان Traefik v2 و v3
مهاجرت از Traefik v2 به v3 عمدتاً شامل تغییر نامهاست؛ مشهورترین مورد، تبدیل middleware با نام ipWhiteList به ipAllowList است. فراتر از این، نسخه v3 سینتکس قوانین router را سختگیرانهتر کرده است (PathPrefix دیگر از قابلیتهای regex پشتیبانی نمیکند، چندین matcher تغییر نام یافته یا حذف شدهاند)، برخی از providerها و گزینهها را بهطور کامل کنار گذاشته و سایر بخشها را بدون تغییر حفظ کرده است: entrypointها، تنظیمات گواهی ACME، گردش کار Docker labels و تمام acme.json شما بدون مشکل منتقل میشوند. نسخه v3 همچنین دارای یک حالت سازگاری (compatibility mode) است که سینتکس قوانین v2 را فعال نگه میدارد؛ بنابراین میتوانید ابتدا فایل باینری را ارتقا دهید و قوانین را بهجای یک شب پرخطر، برای هر سرویس بهصورت جداگانه بازنویسی کنید.
این راهنما فرض را بر استفاده از تنظیمات مبتنی بر label در Docker Compose از راهنمای reverse proxy با Traefik میگذارد. آن صفحه با v3 سازگار است؛ این راهنما برای سروری است که همچنان از تگ traefik:v2 استفاده میکند.
تغییر نامها و حذفها
- عبارت
ipWhiteListاکنون بهipAllowListتغییر یافته است؛ این موضوع هم برای میانافزار (middleware) HTTP و هم برای TCP صدق میکند. گزینههای داخلی آن بدون تغییر باقی ماندهاند، بنابراینsourcerangeدقیقاً همان معنای قبلی خود را حفظ میکند. نسخههای فعلی v3، از جمله v3.7، همچنان نام قدیمی را به عنوان یک نام مستعار منسوخ (deprecated alias) میپذیرند و لیست را اعمال میکنند، اما یک هشدار منسوخشدن در لاگ ثبت میکنند؛ بنابراین این تغییر نام باعث از کار افتادن سرویس نمیشود. با این حال، آن را تغییر دهید: نام قدیمی منسوخ شده است و v2.11 نیز از قبلipAllowListرا میشناسد، پس میتوانید پیش از ارتقا، این تغییر نام را اعمال کنید. - عبارت
providers.docker.swarmMode=trueحذف شده است. Swarm اکنون ارائهدهنده (provider) اختصاصی خود را دارد که به عنوانproviders.swarm.endpointپیکربندی میشود. - بخش
pilotبهطور کامل حذف شده است. - عبارت
experimental.http3حذف شده است. HTTP/3 اکنون مستقیماً در entrypoint فعال میشود. - عبارت
tls.caOptionalاز ارائهدهندهها و از میانافزار forwardAuth حذف شده است. اگر آن میانافزار در مقابل یک سرویس Authentik SSO خودمیزبان قرار دارد، حذف خطcaOptionalتمام کاری است که برای مهاجرت آن باید انجام دهید، زیرا آدرس forwardAuth، هدرهای مورد اعتماد و outpost پشت آنها، همگی در v3 به همان شکل سابق عمل میکنند. - ارائهدهنده متریک InfluxDB v1، ارائهدهنده Rancher و ارائهدهنده Marathon حذف شدهاند.
- قابلیت Tracing به OpenTelemetry منتقل شده است. بکاندهای اختصاصی tracing، از جمله یکپارچهسازیهای Jaeger و Zipkin، حذف شدهاند و v3 اکنون به جای آنها از OTLP (پروتکل OpenTelemetry) خروجی میگیرد.
- گزینههای منسوخ
ssl*در داخل میانافزار headers (مانندsslRedirect،sslHostو موارد دیگر) حذف شدهاند. تغییر مسیرهای (redirection) مربوط به entrypoint و میانافزار redirectScheme جایگزین آنها شدهاند.
این حذفها اهمیت بیشتری از آنچه به نظر میرسد دارند، زیرا اگر پیکربندی استاتیک Traefik حاوی گزینهای باشد که حذف شده یا برای آن ناشناخته است، 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 و نام گره (node) میشود. پیش از تغییر تگ image، پیکربندی استاتیک را پاکسازی کنید.
نام میانافزاری که Traefik واقعاً آن را نمیشناسد (یک غلط تایپی یا نامی که حذف شده و جایگزین نشده است) به شکل متفاوتی باعث شکست میشود: روتری که به آن ارجاع میدهد به جای ایجاد یک مسیر، با خطا بارگذاری میشود، داشبورد آن را علامتگذاری میکند و API گزارش middleware "offce@docker" does not exist را میدهد. درخواستها به آن نام دامنه با خطای 404 مواجه میشوند زیرا روتر هرگز فعال نشده است. توجه داشته باشید که ipwhitelist در نسخههای فعلی v3 در این دسته قرار نمیگیرد: این مورد به عنوان یک نام مستعار منسوخ باقی مانده است، بنابراین برچسبی که تغییر نام داده نشده باشد، همچنان بدون مشکل به کار خود ادامه میدهد.
تغییرات در نحو قوانین
قوانین (Rules) بخشهایی هستند که بازنویسی واقعی در آنها رخ میدهد. تغییرات در نسخه v3 به شرح زیر است:
- استفاده از کوتیشن تغییر نکرده است. هر دو نسخه مقادیر قوانین را در backtick یا دابلکوتیشنِ escape شده میپذیرند و سینگلکوتیشن را رد میکنند؛ بنابراین Host(
app.example.com) و Host("app.example.com") با دابلکوتیشنِ escape شده، همچنان معتبر باقی میمانند. - عبارت
PathPrefixدیگر از عبارتهای باقاعده (regular expressions) یا جایگذاریهای سبک{id}پشتیبانی نمیکند. یک قانون v2 مانند PathPrefix(/api/{version:v[0-9]+}) باید به یک matcher از نوعPathRegexpتبدیل شود که با نحو عبارتهای باقاعده Go نوشته شده باشد. - Matcherها اکنون فقط یک مقدار میپذیرند. در 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 همان عملکرد را دارد. - دو matcher جدید اضافه شدهاند:
PathRegexpوQueryRegexp. عبارتClientIPکه برای تطبیق آدرس کلاینت در داخل یک قانون استفاده میشود، از نسخه v2.11 وجود داشته و بدون تغییر باقی مانده است.
خبر خوب این است که یک قانون ساده Host(app.example.com) که با backtick نوشته شده باشد، از قبل با نحو v3 سازگار است. اکثر تنظیمات کوچک Compose دقیقاً از همین روش استفاده میکنند، به این معنی که اکثر labelها بدون نیاز به ویرایش قوانین، مهاجرت میشوند.
پیش از شروع، برچسبهای خود را بازبینی کنید
شما میتوانید حجم مهاجرت خود را با یک جستجوی ساده بسنجید، زیرا هر تغییر در برچسبهای ناسازگار (breaking label change)، الگویی بر جای میگذارد که با grep قابل شناسایی است:
grep -rnE 'ipwhitelist|HostHeader|Headers\(|PathPrefix\(`[^`]*\{|Host\(`[^`]*`,' docker-compose*.ymlهر نتیجه، یک خط برای ویرایش است. ipwhitelist به ipallowlist تبدیل میشود. HostHeader به Host تبدیل میشود. Headers به Header تبدیل میشود. یک جاینگهدار (placeholder) از نوع {...} در داخل PathPrefix به یک تطبیقدهنده (matcher) از نوع PathRegexp تبدیل میشود. یک ویرگول در داخل Host() به دو تطبیقدهنده Host() تبدیل میشود که توسط || به هم متصل شدهاند. صفر نتیجه به این معناست که برچسبهای شما هماکنون با سینتکس v3 سازگار هستند و مهاجرت به پیکربندی ایستا و تگ image محدود میشود. اگر صفحه پر از نتایج است، زمان مناسبی است که از خود بپرسید آیا این همچنان پروکسی مناسبی برای سرور شماست یا خیر؛ و مقایسه Traefik با Nginx و Caddy هزینه بازنویسی را در برابر آنچه دو گزینه دیگر از شما برای هر برنامه میخواهند، قرار میدهد.
مواردی که بدون تغییر باقی میمانند
نقطه ورودها (Entrypoints) و تغییر مسیر HTTP به HTTPS آنها، حلکنندههای ACME با هر دو نوع چالش، exposedByDefault، برچسبهای مسیریاب و سرویس، loadbalancer.server.port، و همچنین داشبورد، همگی در v3 دقیقاً مانند v2 کار میکنند. گواهیهای شما نیز منتقل میشوند، زیرا v3 همچنان فایل acme.json که توسط v2 نوشته شده است را میخواند. با این حال، پیش از شروع کار از فایل نسخه پشتیبان تهیه کنید، چرا که بازگشت به نسخه قبلی (rollback) در صورت از دست دادن این فایل، مستقیماً منجر به برخورد با محدودیت نرخ (rate limit) صدور گواهی تکراری 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. حالت سازگاری فقط سینتکس قوانین را پوشش میدهد. این حالت گزینههای حذفشده را بازنمیگرداند و میانافزارها (middlewares) را برای شما تغییر نام نمیدهد.
گام 3: تغییر نام میانافزارها را در حالی که هنوز روی v2.11 هستید، اعمال کنید. فایلهای compose خود را برای یافتن نامهای قدیمی جستجو کنید: grep -rn ipwhitelist docker-compose*.yml. هر لیبل ipwhitelist را به ipallowlist ویرایش کرده و آن سرویسها را با docker compose up -d بازسازی کنید. نسخهٔ v2.11 از قبل شامل میانافزار IPAllowList است، بنابراین لیبلهای تغییرنامیافته پیش از تغییر نسخه کار میکنند و هشدار منسوخشدن IPWhiteList از لاگهای v2 شما حذف میشود. نسخههای قدیمیتر از v2.11 نام جدید را نمیشناسند، بنابراین اگر در گام 1 نسخهٔ قدیمیتری از v2 را ثابت کردهاید، ابتدا به traefik:v2.11 ارتقا دهید. (اگر موردی از قلم بیفتد، v3 فعلی همچنان نام قدیمی را بهعنوان یک alias منسوخشده میپذیرد، بنابراین لیست همچنان اعمال میشود؛ آن را در نوبت بعدی اصلاح کنید، نه ساعت 2 بامداد.)
گام 4: تگ ایمیج را تغییر دهید. ایمیج Traefik را روی نسخهٔ فعلی v3 تنظیم کنید، traefik:v3.7 تا تاریخ 11 اکتبر 2026 (v3.7.14 آخرین پچ است)، سپس:
docker compose up -d
docker compose logs -f traefikاز آنجا که حالت سازگاری فعال است، قوانین v2 شما همچنان مطابقت دارند و چون تغییر نام میانافزارها قبلاً در v2.11 اعمال شده است، آن روترها بدون مشکل بالا میآیند. یک لاگ سالم نباید شامل خط field not found و خط does not exist باشد.
در مورد بازهٔ زمانی که این گام ایجاد میکند، صادق باشید. روتری که به نام میانافزاری ارجاع میدهد که v3 واقعاً آن را نمیشناسد (به دلیل غلط املایی یا حذف گزینه)، از لحظهٔ شروع به کار Traefik جدید تا زمانی که لیبلهای آن را اصلاح و کانتینر اپلیکیشن مربوطه را بازسازی کنید، از دسترس خارج خواهد بود. اگر یک مسیر واقعاً نباید قطع شود، میانافزار مشکوک را پیش از تغییر نسخه از لیبل middlewares آن روتر حذف کرده و پس از آن دوباره اضافه کنید، و از قبل تصمیم بگیرید که آیا آن مسیر میتواند برای یک دقیقه بدون آن میانافزار کار کند یا خیر.
گام 5: قوانین را سرویس به سرویس مهاجرت دهید. هر بار روی یک اپلیکیشن کار کنید: قانون آن را به سینتکس v3 بازنویسی کنید، فقط همان سرویس را با docker compose up -d app بازسازی کنید و پیش از ادامه، آن را تست کنید. اگر سرویسی دارای قانونی است که هنوز نمیتوانید آن را بازنویسی کنید، به آن روتر تکی لیبل خروج اضطراری traefik.http.routers.app.ruleSyntax=v2 را بدهید و ادامه دهید.
گام 6: حالت سازگاری را غیرفعال کنید. زمانی که تمام قوانین با سینتکس v3 هستند، defaultRuleSyntax و هر لیبل ruleSyntax را حذف کنید، Traefik را ریاستارت کنید و تأیید کنید که تمام روترها در داشبورد همچنان سبز هستند. با فعال بودن حالت سازگاری به کار خود ادامه ندهید: Traefik هر دو گزینه را در v3.4 منسوخ کرده و در نسخهٔ اصلی بعدی حذف میکند، بنابراین آنها یک پل هستند، نه مقصد نهایی.
پیش و پس از تغییر: برچسبهای یک سرویس
در اینجا برنامهای را میبینید که تمام تغییرات مهم را بهطور همزمان اعمال کرده است: یک Host چندمقداری، یک جایگیر (placeholder) 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 چندمقداری خود را به دو تطبیقدهنده (matcher) که با || به هم متصل شدهاند تقسیم کرد و جایگیر را با PathRegexp عوض کرد؛ همچنین برچسب میانافزار، ipwhitelist را با ipallowlist جایگزین نمود. نقطه ورود (entrypoint)، حلکننده گواهی (certificate resolver)، اتصال روتر به میانافزار و پورت سرویس بدون تغییر باقی ماندند.
تست هر سرویس با استفاده از داشبورد
پس از هر تغییر، صفحه HTTP routers در داشبورد را باز کنید. وضعیت هر router باید سبز باشد. routerهایی که دارای نشان خطا هستند، مشکل دقیق خود را نمایش میدهند؛ این مشکل معمولاً به دلیل وجود یک middleware است که با نام جدیدش شناخته نمیشود یا قانونی است که نسخه v3 قادر به تجزیه آن نیست. سپس از خارج از شبکه، تکتک نامهای دامنه را بررسی کنید:
curl -sI https://app.example.com/api/v1/statusیک 200 یا تغییر مسیر (redirect) عادی برنامه شما، به این معناست که مسیریابی و TLS هر دو بهدرستی کار میکنند. دریافت 404 از Traefik به این معناست که router بالا نیامده است؛ به داشبورد بازگردید و خطای آن را بخوانید. در حین کار، docker compose logs -f traefik را در یک ترمینال دوم باز نگه دارید، زیرا هر خطای تجزیه (parsing failure) در لحظه restart شدن container در آنجا ثبت میشود.
صداقت در بازگشت به نسخه قبل (Rollback)
فایل compose نسخه v2، پیکربندی ایستا و نسخه پشتیبان acme.json را تا زمانی که تمام سرویسها روی v3 مسیریابی شوند و بهطور کامل تست گردند، نگه دارید. بازگشت به نسخه قبل (Rollback) به معنای checkout کردن commit پیش از مهاجرت و اجرای docker compose up -d است. این کار باید برای کل فایل انجام شود، نه فقط تغییر image tag؛ زیرا سینتکس اختصاصی v3 در v2 همانقدر اشتباه است که سینتکس v2 در v3 بود: یک matcher از نوع PathRegexp در آنجا parse نخواهد شد. برچسبهای تغییرنامیافته ipallowlist در نسخه v2.11 مشکلی ندارند، اما در نسخههای قدیمیتر v2 که نام جدید را نمیشناسند، کار نخواهند کرد. اگر acme.json در طول مسیر از دست رفته یا آسیب دیده است، پیش از شروع v2 نسخه پشتیبان را بازیابی کنید تا فرآیند بازگشت به نسخه قبل، محدودیت نرخ (rate limit) سرویس Let's Encrypt شما را با صدور همزمان پنج گواهی مصرف نکند.
FAQ
آیا باید تمام قوانین روتر را برای Traefik v3 بازنویسی کنم؟
خیر. یک قانون ساده Host(app.example.com) که با backtick نوشته شده باشد، در هر دو نسخه معتبر است و اکثر تنظیمات Compose را پوشش میدهد. بازنویسی فقط در مواردی لازم است که قانون از ویژگیهای مختص v2 استفاده کرده باشد: regex یا جایگذارها (placeholders) در داخل Path و PathPrefix، چندین نام دامنه در یک Host()، یا matchers حذفشده شامل Headers، HeadersRegexp و HostHeader.
چه اتفاقی برای ipWhiteList در Traefik v3 افتاده است؟
نام آن به ipAllowList تغییر یافته است، در حالی که پیکربندی داخلی آن بدون تغییر باقی مانده است؛ بنابراین یک label در نسخه v2 مانند traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24 به همان خط با نام ipallowlist تبدیل میشود. نسخه v2.11 از قبل این نام جدید را میپذیرد، بنابراین میتوانید پیش از ارتقا نام را تغییر دهید. نسخههای فعلی v3، از جمله v3.7، همچنان نام قدیمی را به عنوان یک alias منسوخ (deprecated) میپذیرند، بنابراین label تغییرنیافته همچنان لیست مجاز را اعمال میکند و فقط یک هشدار در لاگ ثبت میشود. این وضعیت را به عنوان یک مهلت موقت در نظر بگیرید، نه دلیلی برای نادیده گرفتن تغییر نام: نامهای منسوخ مواردی هستند که ممکن است در یک release حذف شوند، و نام middlewareای که Traefik واقعاً آن را نمیشناسد، با خطای شدید مواجه میشود که منجر به خطای روتر و کد 404 میگردد. داشبورد این خطا را نمایش میدهد و درخواستها به آن نام دامنه با 404 پاسخ داده میشوند.
آیا Traefik v3 همچنان میتواند سینتکس قوانین v2 را بخواند؟
بله. گزینه core.defaultRuleSyntax: v2 را در پیکربندی استاتیک تنظیم کنید تا در حین مهاجرت، سینتکس v2 به عنوان پیشفرض باقی بماند، و پس از تغییر مجدد پیشفرض، از label اختصاصی روتر یعنی ruleSyntax=v2 برای موارد باقیمانده استفاده کنید. هر دو را موقتی بدانید: Traefik آنها را در v3.4 منسوخ اعلام کرده و در نسخه اصلی بعدی حذف خواهد کرد.
آیا گواهیهای Let's Encrypt من پس از ارتقا باقی میمانند؟
بله. Traefik v3 همچنان فایل acme.json که توسط v2 نوشته شده است را میخواند، بنابراین گواهیها صرفاً به دلیل تغییر فایل باینری دوباره صادر نمیشوند. با این حال، پیش از شروع کار، فایل را در جای امنی کپی کنید؛ زیرا بازگشت به نسخه قبل (rollback) یا حذف volumeای که باعث از دست رفتن acme.json شود، منجر به صدور مجدد تمام گواهیها به صورت یکجا میشود و Let's Encrypt تنها اجازه صدور پنج گواهی تکراری در هفته برای یک مجموعه از نامهای دامنه را میدهد.
چرا Traefik v3 پس از ارتقا اجرا نمیشود؟
تقریباً همیشه به این دلیل است که پیکربندی استاتیک هنوز شامل گزینهای است که در v3 حذف شده است و Traefik از اجرای برنامه با گزینههایی که نمیشناسد خودداری میکند. برای موارد باقیمانده شناختهشده (pilot، providers.docker.swarmMode، experimental.http3 و tls.caOptional در بخش providers)، لاگ نام گزینه مشکلساز را ذکر کرده و سپس عبارت incompatible deprecated install configuration option found (یا incompatible deprecated static option found در v3.4 و نسخههای قدیمیتر) را نمایش میدهد؛ برای هر چیزی که v3 هرگز آن را نشناخته است، مانند یک غلط تایپی، عبارت field not found را به همراه گره (node) مربوطه اعلام میکند. هر کدام را حذف یا جایگزین کنید و سپس container را دوباره اجرا کنید.