SSD Nodes Learn Hosting plans →
מדריכים Matt Connorמאת Matt Connor · עודכן 2026-09-02

שדרוג Traefik מ־v2 ל־v3: מה נשבר ואיך מתקנים

Traefik v3 לא יופעל אם swarmMode או pilot נשארו בהגדרה הסטטית. כך מתקנים את השגיאה incompatible deprecated static option found ומשכתבים את כללי הנתב.

מה משתנה בין Traefik v2 ל־v3

המעבר מ־Traefik v2 ל־v3 הוא בעיקר משימת שינוי שמות. השינוי הידוע ביותר הוא החלפת שם ה־middleware ‏ipWhiteList ל־ipAllowList. מעבר לכך, v3 מחמיר את תחביר כללי ה־router: ‏PathPrefix מאבד את יכולות הביטויים הרגולריים שלו, וכמה matchers משנים את שמם או מוסרים. כמה providers ואפשרויות מוסרים לחלוטין. כל שאר הרכיבים ממשיכים לפעול: entrypoints, הגדרת תעודות ACME, תהליך העבודה עם Docker labels, וגם ה־acme.json שלך. v3 כולל גם מצב תאימות שממשיך לתמוך בתחביר הכללים של v2. כך אפשר לשדרג תחילה את קובץ ההפעלה, ולאחר מכן לשכתב את הכללים עבור שירות אחד בכל פעם, במקום לבצע שינוי מסוכן בערב אחד.

מדריך זה מניח שימוש בהגדרת Docker Compose המבוססת על labels, מתוך מדריך ה־reverse proxy של Traefik. הדף ההוא מותאם ל־v3. מדריך זה מיועד לשרת שעדיין מריץ תגית `traefik:v2`.

שינויי השמות וההסרות

  • ipWhiteList נקרא כעת ipAllowList, הן עבור תווכת HTTP והן עבור תווכת TCP. האפשרויות שבתוכו לא השתנו, ולכן sourcerange שומר על משמעותו המדויקת. מהדורות v3 הנוכחיות, כולל v3.5, עדיין מקבלות את השם הישן ככינוי שהוצא משימוש וממשיכות לאכוף את הרשימה. לכן שינוי השם הזה לבדו אינו משבית דבר בעת המעבר. עם זאת, יש לשנות את השם: הכינוי מיועד להסרה, והוא ייעלם מרשימת האפשרויות שהוצאו משימוש ללא הודעה מפורשת.
  • providers.docker.swarmMode=true הוסר. ל־Swarm יש ספק משלו, שמוגדר באמצעות providers.swarm.endpoint.
  • המקטע pilot הוסר לחלוטין.
  • experimental.http3 הוסר. HTTP/3 מופעל ישירות ב־entrypoint.
  • tls.caOptional הוסר מרשימת הספקים ומתוכנת התווכה forwardAuth. אם תווכת זו משמשת חזית ל־מערכת SSO עצמאית של Authentik, מחיקת השורה caOptional היא כל הנדרש לצורך המעבר. כתובת ה־forwardAuth, הכותרות המהימנות וה־outpost שמאחוריהן מתנהגים כולם באותו אופן ב־v3.
  • ספק המדדים InfluxDB v1, ספק Rancher וספק Marathon הוסרו.
  • המעקב עבר ל־OpenTelemetry. תשתיות המעקב הייעודיות, ובהן האינטגרציות עם Jaeger ו־Zipkin, הוסרו, ובמקומן v3 מייצאת נתונים באמצעות OTLP, פרוטוקול OpenTelemetry.
  • האפשרויות ssl* שהוצאו משימוש בתוך תווכת headers, כולל sslRedirect, sslHost והאפשרויות האחרות, הוסרו. הפניות של entrypoint ותווכת redirectScheme החליפו אותן.

להסרות האלה יש חשיבות רבה יותר מכפי שנדמה, משום ש־Traefik מסרבת לעלות כאשר בתצורה הסטטית שלה קיימת אפשרות שאינה מוכרת לה. שורה שנותרה עם pilot או swarmMode עוצרת את המכולה בעת האתחול ומציגה הודעת incompatible deprecated static option found שמציינת את האפשרות שנותרה. אפשרות ש־Traefik מעולם לא הכירה, כגון שגיאת כתיב או tls.caOptional, עוצרת אותה עם field not found. נקו את התצורה הסטטית לפני שתשנו את תגית ה־image.

שם של תווכה ש־Traefik באמת אינה מכירה, כגון שגיאת כתיב או שם שהוסר ולא הוגדר עבורו כינוי, נכשל באופן אחר: ה־router שמפנה אליו נטען עם שגיאה במקום עם נתיב, ה־dashboard מסמן אותו, וה־API מדווח על middleware "offce@docker" does not exist. בקשות לשם המתחם הזה מקבלות 404, משום שה־router מעולם לא עלה. שימו לב ש־ipwhitelist אינו שייך לקטגוריה הזו ב־v3 הנוכחית: הוא נשאר ככינוי שהוצא משימוש, ולכן label שלא שונה ממשיך לעבוד ללא הפרעה.

תחביר הכללים משתנה

בכללים מתבצעת עיקר ההמרה. אלה השינויים ב־v3:

  • יש להקיף ערכים בתוך matchers בתווי backtick. ב־v2 התקבלו גם מרכאות כפולות, אך v3 אינו מקבל אותן. לכן Host("app.example.com") חייב להפוך ל־Host(app.example.com).
  • `PathPrefix אינו תומך עוד בביטויים רגולריים או בממלאי מקום בסגנון {id}. כלל v2 כגון PathPrefix(/api/{version:v[0-9]+}) חייב להפוך ל־matcher מסוג PathRegexp`, שנכתב בתחביר של ביטויים רגולריים ב־Go.
  • Matchers מקבלים כעת ערך יחיד. ב־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.
  • נוספו שני matchers: `QueryRegexp, וכן ClientIP` להתאמת כתובת הלקוח בתוך כלל.

החדשות הטובות הן שכלל Host(app.example.com) פשוט, שנכתב באמצעות תווי backtick, כבר תקין בתחביר של v3. רוב הגדרות Compose הקטנות משתמשות בדיוק בצורה זו, ולכן ברוב המקרים אפשר להעביר את ה־labels בלי לשנות את הכללים כלל.

בקרו בתוויות שלכם לפני שתתחילו

אפשר למדוד את היקף ההגירה באמצעות חיפוש אחד, משום שכל שינוי שובר תאימות בתווית משאיר תבנית ש־grep יכול למצוא:

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

כל תוצאה היא שורה אחת לעריכה. ipwhitelist הופך ל־ipallowlist. HostHeader הופך ל־Host. Headers הופך ל־Header. מציין מיקום {...} בתוך PathPrefix הופך לביטוי התאמה מסוג PathRegexp. פסיק בתוך Host() הופך לשני ביטויי התאמה מסוג Host(), המחוברים באמצעות ||. אפס תוצאות פירושו שהתוויות שלכם כבר משתמשות בתחביר v3 תקין, וההגירה מצטמצמת לתצורה הסטטית ולתגית התמונה. מסך מלא בתוצאות הוא גם זמן מתאים לשאול אם זה עדיין ה־proxy המתאים לשרת, והמאמר כיצד Traefik משתווה ל־Nginx ול־Caddy משווה את עלות השכתוב למה ששני המוצרים האחרים דורשים מכם עבור כל יישום.

מה נשאר ללא שינוי

נקודות הכניסה וההפניה שלהן מ־HTTP ל־HTTPS, פותרי ה־ACME עם שני סוגי האתגרים, exposedByDefault, התוויות של הנתבים והשירותים, loadbalancer.server.port, ולוח הבקרה — כולם פועלים ב־v3 כפי שפעלו ב־v2. גם התעודות שלכם נשמרות, משום ש־v3 ממשיך לקרוא את acme.json ש־v2 יצר. עם זאת, גבו את הקובץ לפני שתתחילו, משום ש־rollback שמאבד אותו עלול לגרום ישירות לחריגה ממגבלת Let's Encrypt להנפקת תעודות כפולות:

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

נתיב ההעברה

שלב 1: קבעו במדויק מה מופעל כיום. החליפו כל תגית traefik:latest או traefik:v2 במהדורה המדויקת שבה אתם משתמשים, לדוגמה traefik:v2.11, ובצעו commit של כל תיקיית 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

לחלופין, הגדירו זאת כדגל ברשימת compose של command:: --core.defaultRuleSyntax=v2. מצב תאימות חל רק על תחביר הכללים. הוא אינו מחזיר אפשרויות שהוסרו ואינו משנה עבורכם את שמות ה־middlewares.

שלב 3: הכינו את שינויי שמות ה־middlewares. חפשו בקובצי compose את השמות הישנים: grep -rn ipwhitelist docker-compose*.yml. ערכו כל תווית ipwhitelist ל־ipallowlist, אך אל תחילו את השינוי עדיין, משום שהשם החדש אינו קיים ב־v2. שינויים אלה יופעלו יחד עם המעבר בשלב הבא. (אם שם אחד יישאר ללא שינוי, v3 הנוכחית עדיין מכבדת את השם הישן ככינוי מסומן כמיושן, ולכן רשימת ההרשאות ממשיכה להיאכף; תקנו זאת בסבב הבא ולא בשעה 2am.)

שלב 4: החליפו את תגית ה־image. הגדירו את ה־image של Traefik למהדורת v3 הנוכחית, traefik:v3.5 בעת כתיבת מדריך זה, ולאחר מכן:

docker compose up -d
docker compose logs -f traefik

מכיוון שמצב התאימות פעיל, כללי v2 שלכם ממשיכים להתאים. בנוסף, מכיוון ש־up -d שיחזר מחדש גם את השירותים שתוויות ה־middleware שלהם שונו, ה־routers האלה עולים ללא שגיאות. לוג תקין אינו כולל שורה של field not found ואינו כולל שורה של does not exist.

עליכם להעריך בכנות את חלון הזמן שנפתח בשלב הזה. Router שמפנה לשם middleware ש־v3 באמת אינה מכירה, עקב שגיאת כתיב או אפשרות שהוסרה, מושבת מהרגע שבו Traefik החדש מופעל ועד שמכולת היישום שלו משוחזרת. בשרת יחיד מדובר בכמה שניות ש־docker compose up -d נדרש כדי לעבור על הרשימה. אם נתיב מסוים אינו יכול לסבול אפילו הפסקה קצרה, הסירו את ה־middleware ששמו שונה מתווית middlewares של אותו router לפני המעבר, והוסיפו אותו מחדש לאחר מכן. קבעו מראש אם הנתיב יכול לפעול במשך הדקה שבאמצע ללא רשימת ה־IP allow שלו.

שלב 5: העבירו את הכללים שירות אחר שירות. עברו על יישום אחד בכל פעם: כתבו מחדש את הכלל שלו בתחביר של v3, שחזרו רק את השירות הזה באמצעות docker compose up -d app, ובדקו אותו לפני שתמשיכו. אם לשירות מסוים יש כלל שעדיין אינכם יכולים לכתוב מחדש, הוסיפו ל־router היחיד הזה את תווית המעקף traefik.http.routers.app.ruleSyntax=v2 והמשיכו.

שלב 6: השביתו את מצב התאימות. לאחר שכל הכללים כתובים בתחביר של v3, מחקו את defaultRuleSyntax ואת כל תוויות ruleSyntax, הפעילו מחדש את Traefik, ואשרו שכל ה־routers עדיין מסומנים בירוק בלוח הבקרה. אל תשאירו את מצב התאימות פעיל דרך קבע: 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 מרובה־הערכים שלו לשני matchers המחוברים באמצעות ||, והחליף את מציין המיקום ב־PathRegexp. תווית התווכה החליפה את ipwhitelist ב־ipallowlist. ה־entrypoint, פותר התעודות, החיבור בין ה־router לתווכה ופורט השירות לא השתנו.

בדקו כל שירות באמצעות לוח הבקרה

לאחר כל שינוי, פתחו את דף נתבי ה־HTTP בלוח הבקרה. כל נתב אמור להופיע בירוק. נתב שמציג תג שגיאה מציין את הבעיה המדויקת. בדרך כלל מדובר ב־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 וייבדקו בפועל. החזרה לאחור פירושה מעבר ל־commit שקדם להעברה והרצת docker compose up -d. יש להחזיר את הקובץ כולו, ולא רק את תגית ה־image, משום שתוויות הייחודיות ל־v3 שגויות תחת v2 בדיוק כפי שתוויות v2 היו שגויות תחת v3: ipallowlist אינו קיים ב־v2, וגם matcher מסוג PathRegexp לא יעבור parsing שם. אם acme.json אבד או נפגם במהלך התהליך, שחזרו את עותק הגיבוי לפני הפעלת v2. כך תהליך ההחזרה לא יבזבז את מכסת rate limit של Let's Encrypt על הנפקה מחדש של חמישה certificates בבת אחת.

FAQ

האם עליי לכתוב מחדש כל כלל ניתוב עבור Traefik v3?

לא. כלל Host(app.example.com) פשוט, שנכתב באמצעות backticks, תקף בשתי הגרסאות, והוא מתאים לרוב הגדרות Compose. יש צורך בכתיבה מחדש רק כאשר כלל השתמש בתכונות שהיו זמינות ב־v2 בלבד: regex או מצייני מקום בתוך Path ו־PathPrefix, כמה שמות מתחם בתוך Host() אחד, מרכאות במקום backticks, או ה־matchers שהוסרו Headers, HeadersRegexp ו־HostHeader.

מה קרה ל־ipWhiteList ב־Traefik v3?

השם שונה ל־ipAllowList, ללא שינוי בתצורה שבתוכו. לכן label של v2 כמו traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24 הופך לאותה שורה, עם ipallowlist בתוכה. גרסאות v3 עדכניות, כולל v3.5, עדיין מקבלות את השם הישן כ־alias שהוצא משימוש. לכן label שלא שונה ממשיך לאכוף את allowlist ללא הודעה בולטת. יש להתייחס לכך כאל פתרון זמני, ולא כסיבה לדחות את שינוי השם. ה־alias צפוי להיות מוסר, ושם middleware ש־Traefik אינו מזהה באמת יגרום לכשל ברור, עם שגיאת router ו־404. לוח הבקרה מציג את השגיאה, ובקשות לשם המתחם הזה מחזירות 404.

האם Traefik v3 עדיין יכול לקרוא תחביר כללים של v2?

כן. הגדירו core.defaultRuleSyntax: v2 בתצורה הסטטית כדי להשאיר את תחביר v2 כברירת המחדל במהלך ההגירה, והשתמשו ב־label ‏ruleSyntax=v2 ברמת ה־router עבור מקרים בודדים שנותרו לאחר החלפת ברירת המחדל. התייחסו לשתי האפשרויות כאל פתרון זמני. 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), הלוג מציין incompatible deprecated static option found ומציג את האפשרות הבעייתית. עבור אפשרות ש־v3 מעולם לא הכירה, כגון tls.caOptional, הוא מציין field not found יחד עם הצומת. מחקו או החליפו כל אחת מהאפשרויות, ולאחר מכן הפעילו שוב את המכולה.