SSD Nodes Learn
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-07-22

ترحيل Traefik من v2 إلى v3 خطوة بخطوة

يعيد Traefik v3 تسمية الوسيط ipWhiteList إلى ipAllowList ويغيّر صيغة قواعد التوجيه. رقِّ من v2 بوضع التوافق، ثم رحّل تسميات الخدمات واحدة تلو الأخرى.

ما الذي يتغيّر بين Traefik v2 وv3

ترحيل Traefik من v2 إلى v3 هو في معظمه عملية إعادة تسمية، وأشهر ما يُعاد تسميته هو الوسيط (middleware) ipWhiteList الذي يصبح ipAllowList. وفيما عدا ذلك، تُشدّد v3 صيغة قواعد الموجّه (router) — يفقد PathPrefix ميزاته الخاصة بالتعبيرات النمطية (regex)، وتُعاد تسمية عدة مطابِقات (matchers) أو تُحذف — وتُسقط تمامًا بضعة مزوّدين (providers) وخيارات، وتُبقي كل شيء آخر عاملًا: نقاط الدخول (entrypoints)، وإعداد شهادات ACME، ومسار عمل تسميات Docker، وملف acme.json الخاص بك، كلها تنتقل معك دون تغيير. وتأتي v3 أيضًا بوضع توافق (compatibility mode) يُبقي صيغة قواعد v2 عاملة، ما يتيح لك ترقية الملف التنفيذي أولًا ثم إعادة كتابة القواعد خدمة تلو الأخرى بدلًا من ليلة واحدة محفوفة بالمخاطر.

يفترض هذا الدليل إعداد Docker Compose القائم على التسميات (labels) من دليل وكيل Traefik العكسي. تلك الصفحة مصمَّمة أصلًا لإصدار v3 (v3-native)؛ أما هذه فهي للجهاز الذي ما زال يشغّل وسم traefik:v2.

إعادة التسمية والحذف

  • أصبح ipWhiteList الآن ipAllowList، لكلا الوسيطين HTTP وTCP. الخيارات الداخلية لم تتغيّر، لذا يحتفظ sourcerange بمعناه الدقيق نفسه. إصدارات v3 الحالية، بما فيها v3.5، ما زالت تقبل الاسم القديم كاسم بديل مهجور (deprecated alias) وتواصل تطبيق اللائحة، لذا فإن هذه التسمية الجديدة وحدها لا تُسقط شيئًا عند الانتقال. أعد تسميته على أي حال: فالاسم البديل مقرَّر حذفه، ويختفي من قائمة الإهمال بصمت، لا بضجيج.
  • اختفى providers.docker.swarmMode=true. صار لـ Swarm مزوّده (provider) الخاص، يُضبط عبر providers.swarm.endpoint.
  • اختفى قسم pilot كليًا.
  • اختفى experimental.http3. يُفعَّل HTTP/3 مباشرة على نقطة الدخول (entrypoint).
  • اختفى tls.caOptional من المزوّدين ومن وسيط forwardAuth.
  • اختفى مزوّد مقاييس InfluxDB v1، ومزوّد Rancher، ومزوّد Marathon.
  • انتقل التتبّع (tracing) إلى OpenTelemetry. اختفت الواجهات الخلفية (backends) المخصصة للتتبّع، ومن بينها تكاملا Jaeger وZipkin، وتُصدِّر v3 بدلًا من ذلك عبر OTLP (بروتوكول OpenTelemetry).
  • اختفت خيارات ssl* المهملة داخل وسيط headers (sslRedirect، وsslHost، وبقيتها). حلّت محلها إعادات توجيه نقطة الدخول ووسيط redirectScheme.

هذه المحذوفات أهم مما تبدو عليه، لأن Traefik يرفض البدء إذا احتوت إعداداته الثابتة (static configuration) على خيار لا يعرفه. سطر pilot أو swarmMode متروك خلفك يوقف الحاوية عند الإقلاع برسالة incompatible deprecated static option found تسمّي العنصر المتروك؛ أما خيار لم يسمع به Traefik إطلاقًا (خطأ إملائي، أو tls.caOptional) فيوقفه برسالة field not found بدلًا من ذلك. نظّف الإعدادات الثابتة قبل أن تلمس وسم الصورة (image tag).

اسم وسيط لا يعرفه Traefik فعلًا (خطأ إملائي، أو اسم حُذف بدلًا من أن يُمنَح اسمًا بديلًا) يفشل بطريقة مختلفة: الموجّه الذي يشير إليه يُحمَّل بخطأ بدلًا من مسار، ولوحة التحكم (dashboard) تضع عليه علامة، وواجهة برمجة التطبيقات (API) تُبلغ عن middleware "offce@docker" does not exist. الطلبات إلى ذلك المضيف تحصل على 404 لأن الموجّه لم يقم أبدًا. لاحظ أن ipwhitelist ليست ضمن هذه الفئة على v3 الحالية: فهي تنجو كاسم بديل مهجور، لذا فإن تسمية لم تُغيَّر تواصل العمل بهدوء.

تغييرات صيغة القواعد

في القواعد تحدث إعادة الكتابة الحقيقية. التغييرات في v3:

  • الفواصل الخلفية (backticks) مطلوبة حول القيم داخل المطابِقات. كانت v2 تقبل أيضًا علامات الاقتباس المزدوجة؛ v3 لا تقبلها، لذا فإن Host("app.example.com") يجب أن يصبح Host(app.example.com).
  • لم يعد PathPrefix يفهم التعبيرات النمطية أو العناصر النائبة (placeholders) من طراز {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.
  • هناك مطابِقان جديدان: QueryRegexp، وClientIP لمطابقة عنوان العميل داخل قاعدة.

الخبر السار: قاعدة 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، ويتقلّص الترحيل إلى الإعدادات الثابتة ووسم الصورة فقط.

ما الذي يبقى كما هو

نقاط الدخول وإعادة توجيهها من HTTP إلى HTTPS، ومحلّلات ACME (ACME resolvers) بنوعي التحدي (challenge) كليهما، وexposedByDefault، وتسميات الموجّه والخدمة، وloadbalancer.server.port، ولوحة التحكم، كل ذلك يعمل في 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

أو كخيار (flag) في قائمة command: الخاصة بـ compose: --core.defaultRuleSyntax=v2. وضع التوافق يغطي صيغة القواعد فقط. لا يُحيي الخيارات المحذوفة، ولا يعيد تسمية الوسائط نيابة عنك.

الخطوة 3: جهّز إعادة تسمية الوسائط. ابحث في ملفات compose عن الأسماء القديمة: grep -rn ipwhitelist docker-compose*.yml. عدّل كل تسمية ipwhitelist إلى ipallowlist، لكن لا تطبّق التغيير بعد، لأن الاسم الجديد غير موجود في v2. تُطبَّق هذه التعديلات مع الانتقال في الخطوة التالية. (إن أفلتت واحدة منها، فإن v3 الحالية ما زالت تحترم الاسم القديم كاسم بديل مهجور، فتواصل اللائحة عملها؛ أصلحها في الجولة التالية بدلًا من الساعة 2 صباحًا.)

الخطوة 4: بدّل وسم الصورة. اضبط صورة Traefik على إصدار v3 الحالي، traefik:v3.5 وقت كتابة هذا الدليل، ثم:

docker compose up -d
docker compose logs -f traefik

بما أن وضع التوافق مفعّل، تواصل قواعد v2 لديك المطابقة، وبما أن up -d أعاد أيضًا إنشاء الخدمات التي غيّرت تسميات وسائطها، فإن تلك الموجّهات تقوم نظيفة. السجل السليم لا يحوي سطر field not found ولا سطر does not exist.

كن صادقًا مع نفسك بشأن النافذة الزمنية التي تفتحها هذه الخطوة. الموجّه الذي يشير إلى اسم وسيط لا تعرفه v3 فعلًا (خطأ إملائي، أو خيار محذوف) يكون معطلًا من لحظة بدء تشغيل Traefik الجديد وحتى تُعاد إنشاء حاوية تطبيقه، وهو ما يمثل على جهاز واحد الثواني القليلة التي يحتاجها docker compose up -d لتصفّح القائمة. إن كان مسار ما لا يحتمل أي انقطاع حقًا، فأزل الوسيط المُعاد تسميته من تسمية middlewares الخاصة بذلك الموجّه قبل الانتقال وأعده بعده، وقرّر مسبقًا ما إذا كان بإمكان ذلك المسار الاستغناء عن لائحة السماح الخاصة بعناوين IP خلال تلك الدقيقة الفاصلة.

الخطوة 5: رحّل القواعد خدمة تلو الأخرى. اعمل على تطبيق واحد في كل مرة: أعد كتابة قاعدته بصيغة v3، وأعد إنشاء تلك الخدمة وحدها بالأمر docker compose up -d app، واختبرها قبل الانتقال إلى غيرها. إن كانت لدى إحدى الخدمات قاعدة لا تستطيع إعادة كتابتها بعد، فامنح ذلك الموجّه وحده تسمية مخرج الطوارئ traefik.http.routers.app.ruleSyntax=v2 وواصل التقدّم.

الخطوة 6: أطفئ وضع التوافق. حين تصبح كل قاعدة بصيغة v3، احذف defaultRuleSyntax وأي تسميات ruleSyntax، أعد تشغيل Traefik، وتأكد أن كل موجّه ما زال يظهر بالأخضر في لوحة التحكم. لا تستقر ووضع التوافق مفعّل: فقد أهملت Traefik الخيارين معًا في v3.4 وتحذفهما في الإصدار الرئيسي التالي، لذا فهما جسر لا وجهة.

قبل وبعد: تسميات خدمة واحدة

إليك تطبيقًا واحدًا يجمع كل التغييرات الشهيرة دفعة واحدة: Host متعدد القيم، وعنصر نائب في PathPrefix، ووسيط 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، واستبدلت تسمية الوسيط ipwhitelist بـ ipallowlist. نقطة الدخول، ومحلّل الشهادة (certificate resolver)، والربط بين الموجّه والوسيط، ومنفذ الخدمة، كلها بقيت دون تغيير.

اختبر كل خدمة عبر لوحة التحكم

بعد كل انتقال، افتح صفحة موجّهات HTTP في لوحة التحكم. ينبغي أن يكون كل موجّه أخضر. الموجّه الذي يحمل شارة خطأ يسمّي مشكلته بدقة، وعادة ما تكون وسيطًا غير موجود تحت اسمه الجديد أو قاعدة لا تستطيع v3 تحليلها. ثم تأكّد من الخارج، مضيفًا واحدًا في كل مرة:

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

يعني رمز 200 أو إعادة التوجيه الطبيعية لتطبيقك أن التوجيه وTLS نجَوا معًا. رمز 404 من Traefik يعني أن الموجّه لم يقم؛ عد إلى لوحة التحكم واقرأ خطأه. أبقِ docker compose logs -f traefik مفتوحًا في طرفية ثانية أثناء عملك، لأن كل فشل في التحليل يصل إليه فور إعادة تشغيل حاوية.

صراحة بشأن التراجع

احتفظ بملف compose الخاص بـ v2، وبإعداداته الثابتة، وبنسخة acme.json الاحتياطية حتى تُوجَّه كل خدمة على v3 وتُختبَر فعليًا. التراجع يعني عمل checkout إلى commit ما قبل الترحيل وتشغيل docker compose up -d، ويجب أن يكون الملف كاملًا، لا وسم الصورة وحده، لأن التسميات الخاصة بـ v3 فقط غير صحيحة في v2 تمامًا كما لم تكن تسميات v2 صحيحة في v3: ipallowlist غير موجودة في v2، ومطابِق PathRegexp لن يُحلَّل هناك أيضًا. إذا فُقد 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 بدلًا منه. إصدارات v3 الحالية، بما فيها v3.5، ما زالت تقبل الاسم القديم كاسم بديل مهجور، لذا فإن تسمية لم تُغيَّر تواصل تطبيق لائحة السماح بهدوء. عامل ذلك على أنه وقت مستعار لا سببًا لتخطي إعادة التسمية: فالاسم البديل مقرَّر حذفه، واسم وسيط لا تعرفه Traefik فعلًا يفشل بضجيج بدلًا من ذلك، بخطأ في الموجّه ورمز 404. تُظهر لوحة التحكم الخطأ، وتعيد الطلبات إلى ذلك المضيف الرمز 404.

هل ما زال بإمكان Traefik v3 قراءة صيغة قواعد v2؟

نعم. اضبط core.defaultRuleSyntax: v2 في الإعدادات الثابتة لإبقاء صيغة v2 هي الافتراضية أثناء الترحيل، واستخدم تسمية ruleSyntax=v2 الخاصة بكل موجّه للحالات المتأخرة المنفردة بعد أن تعيد الافتراضي إلى v3. عامل الاثنين على أنهما مؤقتان: فقد أهملتهما 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) يقول السجل incompatible deprecated static option found ويسمّي المتسبب؛ أما بالنسبة إلى أي شيء لم تسمع به v3 إطلاقًا، مثل tls.caOptional، فيقول field not found مع اسم العنصر (node). احذف كل واحد منها أو استبدله، ثم أعد تشغيل الحاوية.