קונטיינרים שמסתיימים מיד עם exec format error מעוררים את האינסטינקט השגוי: להוסיף יכולת, לחבר התקן, לערוך את תצורת המנהרה. אף אחד מאלה לא מגיע לבעיה. הליבה לא הצליחה להריץ את הבינארי כלל, מה שבקונטיינר אומר כמעט תמיד שהתמונה מכוונת לארכיטקטורת מעבד שונה מזו של המארח. כל מה שתוכלו לשנות בניתוב, בפרטי ההתחברות או בהרשאות קורה אחרי שתוכנית התחילה, ואף תוכנית לא התחילה.

הודעת האתחול שנראית כמו שגיאת תצורה

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

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

קראו את אינדקס התמונה לפני פקודת ההרצה

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

docker buildx imagetools inspect ghcr.io/example/vpn:1.4
docker image inspect --format '{{.Os}}/{{.Architecture}}' ghcr.io/example/vpn:1.4

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

תגים בוחרים וריאנט; הם לא יוצרים אותו

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

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

אמולציה היא הסדר, לא שכבת תרגום

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

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

הרשאות פותרות בעיה אחרת

מתן יכולת ניהול רשת או העברת התקן TUN לא יכול לגרום לקובץ הפעלה לא תואם לרוץ. אלה הרשאות הרצה שתהליך פועל משתמש בהן; הן בלתי נראות למטעין שכבר סירב לקובץ.

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

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

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