מושגים בסיסיים ב Docker: קונטיינרים ואימג'ים
דוקר פותח בחברת איחסון ענן בשם dotCloud (כיום כבר שינתה את שמה ל Docker Inc) בשנת 2013. באותה תקופה דוטקלאוד הציעה מוצר שיודע לקחת קוד מהמחשב שלכם ולהעלות אותו להרצה בענן שלהם - והבעיה המרכזית שהיתה להם היתה איך להעביר את הקוד ממכונה אחת לשניה בלי לשבור אותו.
עד לפיתוח של דוקר בשביל להעביר קוד ממקום למקום היית צריך לשכפל את "הדברים החשובים בסביבת הריצה" למכונה החדשה. אז אם יש לי תוכנית פייתון שצריכה לרוץ על שרת, אני צריך להתקין על השרת את אותה גירסת פייתון שעליה עבדתי בפיתוח, את אותן ספריות פייתון שהתוכנית שלי צריכה (עם pip install), והחלק הקשה - את החלקים ממערכת ההפעלה שרלוונטיים לתוכנית שלי. אם התוכנית שלי משתמשת ב Shared Library מסוימת אז אני צריך לוודא שהספריה תותקן גם על השרת. אם התוכנית שלי משתמשת בתוכנית חיצונית מסוימת, אותה תוכנית צריכה להיות מותקנת גם על השרת.
הרבה פעמים אי תאימויות קטנות בין הכלים או הספריות יוצרים באגים שקשה לזהות אותם, ולכן המעבר לפרודקשן דרש תמיד תשומת לב מיוחדת לפרטים.
דוקר היה אמור להיות עבור תעשיית התוכנה מה שקונטיינרים היו לתעשיית הספנות: טכנולוגיה שכל התעשייה תתיישר סביבה, שתאפשר להעביר קוד ממכונה אחת למכונה שניה בצורה אמינה ובלי להתעסק בפרטים. החלום היה שמתכנתת תבנה קופסה, תתן את הקופסה הזאת לצוות Devops ואותו צוות Devops יוכל להפעיל את הקוד שבקופסה על כל מכונה בעולם.
הדרך של דוקר להגשים את החלום הזה היתה שימוש בפיצ'רים של Linux Kernel שמאפשרים להריץ מעין מערכת הפעלה בתוך מערכת הפעלה. סוג של קופסה סגורה בתוך המחשב שיכולה, בתוך העולם שלה, לתת ליישומים סביבת ריצה מלאה שכוללת את כל הספריות אפילו הבסיסיות ביותר של מערכת ההפעלה. דוקר, כטכנולוגיה, מאפשר בניה של קופסאות כאלה והפעלה שלהן בכל מקום.
וזה מביא אותנו לשני המושגים שרציתי לדבר עליהם בפוסט זה: קונטיינרים ואימג'ים.
הקונטיינר הוא אותה קופסה סגורה שרצה על מכונה מסוימת. קונטיינר הוא סביבת ריצה שהיישום או היישומים שרצים בתוכה רואים את עצמם כאילו הם רצים בתוך מערכת הפעלה מסוימת, עם ספריות מסוימות וכלי עבודה מסוימים.
לדוגמה קונטיינר של תוכנית פייתון יכלול גם את קוד התוכנית, גם את פייתון עצמה, גם את כל הספריות שהתוכנית צריכה, וגם את כל הספריות של מערכת ההפעלה והקבצים ממערכת ההפעלה שהתוכנית משתמשת בהם. למעשה זה כאילו לקחנו את כל המחשב מהתוכנית למטה עד מערכת ההפעלה, ארזנו את הכל יחד והרצנו את זה על מכונה אחרת.
על מחשב פיזי אחד אפשר להריץ כמה קונטיינרים שאנחנו רוצים, בדיוק כמו שמריצים תוכניות רגילות. קונטיינר מזכיר מכונה וירטואלית, בגלל שבתוכו רצה מערכת הפעלה מלאה עם כל הכלים והספריות שלה - אבל זו אשליה. הקונטיינר בדוקר הוא תוכנית רגילה, שרצה בתוך מערכת ההפעלה של המחשב המארח. מסיבה זאת הביצועים של קונטיינרים הם מאוד טובים ובתור מתכנתים קל לנו להריץ קונטיינר נפרד לכל אפליקציה שאנחנו עובדים איתה.
ואם קונטיינר הוא תוכנית שכרגע רצה על המכונה בתוך קופסה נפרדת, אז Container Image הוא התבנית שממנה אנחנו מייצרים קונטיינרים. ה Image הוא הדבר שאפשר בקלות לשלוח ממכונה למכונה. היחס בין קונטיינרים לאימג'ים מזכיר את היחס בין קובץ תוכנית לתהליך על המחשב - האימג' הוא הקובץ, וכשמפעילים אותו מקבלים קונטיינר.
המנוע של דוקר (Docker Engine) הוא רכיב תוכנה שיודע לבנות קונטיינר מתוך אימג'. לכן על כל מכונה שמריצה Docker Engine אני יכול לקחת כל אימג' שתואם לו וליצור ממנו קונטיינר.
אימג' בדוקר מורכב מקבצים, וכל קובץ מייצג "שכבה" של נתונים. כשהמנוע צריך להריץ קונטיינר מהאימג', הוא ממזג את כל השכבות למערכת קבצים אחת שכוללת את כל הקבצים מכל השכבות. כתיבה לקובץ באימג' פשוט יוצרת שכבה חדשה. מבנה השכבות של האימג' מאפשר מאוד בקלות ליצור אימג' מתוך אימג', וגם מהווה את הבסיס לבניית הקונטיינרים.
בשביל "להריץ" אימג', כלומר בשביל לבנות קונטיינר מתוך אימג', המנוע של דוקר לוקח את האימג' ומוסיף עליו שכבה חדשה של מערכת קבצים אינטרקטיבית. הוספת השכבה החדשה היא תהליך כמעט מיידי ולכן הרצה של קונטיינר מתוך אימג' היא מאוד מהירה. הצד המפתיע בשיטת העבודה הזאת הוא שקונטיינרים הם ישויות זמניות. אם הקונטיינר כותב קובץ למערכת הקבצים שלו, ברגע שהקונטיינר ייסגר הקובץ ייעלם יחד איתו.
העבודה שלנו עם דוקר כוללת שני מנגנונים שכל אחד מהם מתרחש בזמן שונה:
אנחנו יוצרים אימג'ים על מכונת הפיתוח שלנו כשאנחנו רוצים לסגור קוד מסוים ולהכין אותו למשלוח. סגירת תוכנה שכתבתי באימג' מאפשרת לי להעביר את התוכנה הזאת בצורה אמינה לכל מכונה שמריצה את Docker Engine.
אנחנו מריצים קונטיינרים מתוך אימג'ים כשאנחנו רוצים להשתמש בהם. אז אם אני צריך עכשיו בסיס נתונים אני מריץ קונטיינר של PostgreSQL; אם אני צריך לנסות משהו ב Elixir אני יכול להריץ קונטיינר של אליקסיר; ואם אני רוצה לכתוב מערכת ב Rails אני יכול להריץ קונטיינר של ריילס. כל עוד יש לי את האימג' של משהו, אני יכול ברגע להריץ ממנו קונטיינר או מספר קונטיינרים.
החל מ 2015, דוקר וחברות מובילות נוספות בתעשיה, מתחזקים מבנה קוד פתוח שנקרא OCI (קיצור ל Open Container Initiative) שאחראי על יצירת סטנדרט פתוח לפורמטים של קונטיינרים ואימג'ים.
למידע נוסף על דוקר ואיך המנגנון הזה של קונטיינרים עובד מתחת לפני השטח שווה לקרוא את המאמר בקישור:
https://accenture.github.io/blog/2021/03/10/docker-behind-the-scenes.html