ה-VPN פועל, הדפדפן מגיע לאתרים פנימיים, והקונטיינר עדיין לא מצליח לפתור את אותם שמות. התקנת חבילה נכשלת בשגיאת פתרון שמות כמו EAI_AGAIN, או שיישום לא מוצא מארח מסד נתונים שמכונת המארח פותרת בלי שום תלונה. הקונטיינר לא משתמש במאמת שה-VPN התקין. Docker העתיק את תצורת המאמת של המארח כשהקונטיינר נוצר, ושום דבר לא העתיק אותה שוב לאחר מכן.

שתי תצוגות של המאמת במכונה אחת

ב-Linux, Docker נותן לכל קונטיינר עותק של תצורת המאמת של המארח ברגע היצירה, מסנן כתובות loopback ומריץ שרת DNS מוטמע בכתובת 127.0.0.11 שמעביר שאילתות החוצה. לקוח VPN שמשכתב את /etc/resolv.conf לאחר שהקונטיינר עלה לא משנה דבר בתוכו. הפעלה מחדש של הקונטיינר עוזרת רק אם המאמת של המארח במקרה נכון באותו רגע.

Docker Desktop ב-macOS או Windows מוסיף שכבה, מפני שהדמון חי במכונה וירטואלית. ייתכן שהמאמת של ה-VPN במארח לעולם לא יהיה גלוי ל-VM הזה, ולכן הפעלה מחדש לא משנה דבר בכלל. השוו את שתי התצוגות לפני בחירת תיקון: docker exec mycontainer cat /etc/resolv.conf לצד רשימת המאמתים של המארח.

קונטיינר שמפרט מאמת ציבורי בעוד המארח מפרט מאמת פנימי יפתור שמות ציבוריים וייכשל בפנימיים. הפיצול הזה הוא החתימה של הבעיה הזאת.

אפשרות A: להעביר את מאמת המנהרה לכל קונטיינר

Docker מקבל הגדרות DNS לכל קונטיינר, וזו השינוי הקטן ביותר שעובד. תחילה קראו את כתובות המאמת של ה-VPN: scutil --dns ב-macOS, resolvectl status או פלט המצב של הלקוח עצמו ב-Linux. אחר כך הפעילו את הקונטיינר איתן, למשל docker run --dns 192.168.2.1 --dns 192.168.123.1 myimage. ב-Compose אותה הגדרה היא רשימה תחת השירות, שם היא חיה בבקרת גרסאות ולא בהיסטוריית ה-shell של מישהו.

מערך dns ב-/etc/docker/daemon.json חל על כל קונטיינר חדש, מה שנשמע מסודר יותר וזה לא כך. הוא חל גם כשהמנהרה למטה, ואז מאמת שנגיש רק דרך ה-VPN שובר משיכות תמונות רגילות. הגדרות לכל קונטיינר קלות יותר להצדקה וקלות יותר לביטול.

אפשרות B: לתת לקונטיינר לחלוק את רשת המארח

רשת המארח עוקפת את העותק לגמרי, מפני שהקונטיינר משתמש במאמת של המארח ובמנהרה של המארח. היא גם מסירה את בידוד הרשת שכנראה רציתם, והיא לא מתנהגת אותו דבר תחת Docker Desktop. ב-Linux זו הבחירה הפרגמטית לכלי חד-פעמי שצריך לפתור שמות פנימיים.

עבור builds אף אחת מהאפשרויות לא חלה, מפני ששלבי build לא יורשים דגלי זמן ריצה. בנו עם רשת מארח היכן שהפלטפורמה מאפשרת, או השאירו את התקנת התלויות בשלב שלא צריך את המנהרה.

מה שאף אחת מהאפשרויות לא מתקנת

כתובת DNS חסרת תועלת אם לקונטיינר אין נתיב אליה. מאמת ה-VPN יושב בדרך כלל בתוך מרחב הכתובות של המנהרה, ולכן הקונטיינר צריך נתיב לקידומת הזו. גשר ברירת המחדל של Docker מנתב החוצה דרך המארח בדרך כלל, וזה מספיק כשהמארח מחזיק בנתיב המנהרה והעברה קדימה מופעלת. רשתות גשר מותאמות עם מאגרי כתובות משלהן עלולות להתנגש בתת-הרשת של ה-VPN, ואז השאילתות הולכות למקום אחר לגמרי.

בדקו את תת-הרשת של רשת Docker מול תת-הרשת של ה-VPN לפני שאתם מנפים את המאמת עצמו. חפיפה מייצרת כשל שנראה בדיוק כמו שרת DNS שבור.

לאמת בתוך הקונטיינר

בדקו עם getent hosts db.internal בתוך הקונטיינר ולא עם דפדפן או סביבת ריצה של שפה, מפני שאלה מיישמים מדיניות DNS משלהם ומטמון משלהם. אם getent פותר את השם והיישום עדיין נכשל, המאמת כעת נכון והבעיה הנותרת היא ברמת היישום. אם הוא לא פותר, שלב ה-DNS לא הושלם.

צרו מחדש את הקונטיינר לאחר ששיניתם את הגדרות ה-DNS שלו. עריכת /etc/resolv.conf בתוך קונטיינר פועל נעלמת יחד איתו ומסתירה את בעיית התצורה בדיוק לפרק הזמן שנדרש למישהו להפעיל אותו מחדש.

מאמרים קשורים