בפרק הזה נעשה קפיצת מדרגה ונלמד לבנות בעצמנו אימג'ים מדויקים לפי הצרכים שלנו, באמצעות קובץ מיוחד בשם Dockerfile.
נבין מה זה Dockerfile ולמה הוא כל כך חשוב, נעבור על כל הפקודות המרכזיות כמו FROM, WORKDIR, COPY, RUN, CMD, EXPOSE ועוד – ונתרגל איך לכתוב קובץ Dockerfile נכון מאפס.
נלמד גם איך לבדוק שהקונטיינר שלנו פועל כמו שצריך עם HEALTHCHECK, איך לבנות אימג'ים בצורה מסודרת עם docker build, ואיך להתעלם מקבצים מיותרים עם .dockerignore כדי לשמור על אימג'ים קטנים ונקיים.
שימו לב ! לפני שאתם ממשיכים לעבור על החלק החמישי, תעברו על ארבעת החלקים הראשונים כדי שתבינו על מה מדובר מאחר ובמקרה של דוקר, חשוב מאוד להבין את המושגים ומה בדיוק אנחנו עושים כי הדברים יכולים להיות מבלבלים.
ניתן לעבור על כל החלקים בעמוד המיועד לדוקר בבלוג: מדריך דוקר למתחילים בעברית - כל החלקים
מדריך דוקר למתחילים בעברית חלק 5 – איך כותבים Dockerfile?
1) מה זה Dockerfile ולמה צריך אותו?
2) המבנה הכללי של Dockerfile
3)איך לקבוע את הבסיס שעליו נבנה את האימג' – FROM
4)איך לקבוע את התיקייה שבתוכה ירוצו הפקודות – WORKDIR
5)איך להעתיק קבצים מהמחשב שלנו לתוך האימג'– COPY
6) איך להריץ פקודות במהלך הבנייה של האימג'– RUN
7) איך להגדיר מה הקונטיינר יעשה כשהוא יתחיל לרוץ – CMD
8) איך לציין איזה פורט האפליקציה שלנו תשתמש בו – EXPOSE
9) איך להריץ את הקוד תחת משתמש רגיל ולא תחת Root
10) איך לבדוק אם הקונטיינר באמת חי ופועל כמו שצריך – HEALTHCHECK
11) איך לבנות אימג' בדוקר - Docker Build.
12) איך להתעלם מקבצים\תיקיות בניה של אימג'? - docker ignore
1. מה זה בעצם Docker file ולמה צריך אותו?
1.א. מה זה Docker File?
- מאיזה בסיס להתחיל? זאת אומרת על איזו מערכת הפעלה נריץ את הקונטיינר? (למשל: ubuntu, alpine, node, python)
- אילו קבצים ותיקיות להעתיק פנימה לתוך הקונטיינר?
- נגיד ויש סקריפטים, אפליקציות, תיקיות קוד – מה צריך להיכנס לתוך ה־Image?
- אילו פקודות להריץ בתוך הקונטיינר בזמן הבנייה? התקנת תוכנות, יצירת תיקיות, הרשאות, עדכונים וכו’
- מה להריץ כשהקונטיינר עולה? איזו פקודה צריכה לרוץ אוטומטית כשהקונטיינר מופעל?
- איזו תיקיית עבודה להגדיר כברירת מחדל בתוך הקונטיינר? איפה תתבצע העבודה? (למשל /app)
- האם צריך להגדיר יוזר מיוחד להרצה? או שהכול יתבצע כ-root?
- האם יש משתני סביבה שצריך להגדיר? לדוגמה: ENV NODE_ENV=production
- האם ליצור רשת חדשה או לחבר לרשת קיימת? תלוי אם אתה רוצה בידוד או אינטגרציה עם קונטיינרים אחרים
- האם צריך לפתוח פורטים מסוימים? לדוגמה: 80, 443, 3000, 8080 וכו’
- האם יש Volume שצריך לחבר? כדי שהמידע לא ייעלם כשמכבים את הקונטיינר
- האם צריך לבדוק שהקונטיינר בריא? באמצעות פקודת HEALTHCHECK לבדיקת תקינות (למשל HTTP 200)
- האם יש צורך להגדיר איך לעצור את הקונטיינר בצורה נקייה? הגדרת STOPSIGNAL
- האם להשתמש ב־Shell מיוחד להרצת פקודות RUN? לדוגמה Bash לעומת sh
- האם צריך להוסיף תיוגים או תיאור (LABEL)? למשל: מחבר, גרסה, תיאור של האימג’
- האם צריך לבנות את הקובץ עם פרמטרים (ARG)? למשל: גרסה, סוג אפליקציה, שם תיקייה
- האם צריך להכין פעולות שיתבצעו רק כשמישהו יבנה Image חדש מה־Image הזה? באמצעות ONBUILD
1.ג למה צריך Docker File?
בנוסף, מי שיש לו את הקובץ הזה, יכול לבנות אצלו במערכת בדיוק את אותו Image.
וכמובן – אתם בישלתם, ואתם גם אוכלים: לא צריך לנחש מה יש בפנים – פשוט פותחים את הקובץ ורואים איך האימג' בנוי.
בנוסף, חשוב להבין:
-
קובץ פשוט אבל חזק: Dockerfile הוא בסך הכל קובץ טקסט, אבל דרכו אפשר להקים סביבה שלמה בצורה מסודרת.
-
בנייה זהה בכל מקום: בזכות Dockerfile, לא משנה איפה מריצים את הבנייה – יוצא בדיוק אותו אימג', בלי הפתעות.
-
ניהול גרסאות קל: אפשר לשמור את הקובץ הזה בגיט ולעקוב אחרי שינויים, לשפר גרסאות, ולחזור אחורה אם צריך.
-
חיסכון עצום בזמן: אחרי שמגדירים Dockerfile טוב – בניית האימג'ים לוקחת דקות ולא דורשת התעסקות ידנית.
-
בסיס לעבודה מתקדמת: בעתיד, Dockerfile הופך להיות חלק מפרויקטים יותר גדולים עם Docker Compose, Kubernetes ועוד.
2. המבנה הכללי של Dockerfile
וזהו, מה שזה יעשה, זה להוריד אימג' מבוסס אובונטו, לאחר מכן יבצע התקנה של דברים: apt update && apt install -y htop, ואז בסוף יריץ את הפקודה htop (מי שלא יודע מה זה, יש לנו הסבר על זה במדריך לינוקס למתחילים: כאן).
ברגע שאתם מתחילים לעבוד עם קבצי Dockerfile ויש לכם הרבה פרויקטים,
מומלץ מאוד ליצור תיקייה נפרדת לכל פרויקט, ולשים בה את קובץ ה-Dockerfile יחד עם כל הקבצים שרלוונטיים ל-Image שלכם.
זה יעזור לכם לשמור על סדר ולמנוע בלאגן, כי כשיש הרבה פרויקטים, קל מאוד להתבלבל בזמן יצירת ה-Image.
3.איך לקבוע את הבסיס שעליו נבנה את האימג' – FROM
- שם של מערכת הפעלה:
FROM ubuntu:20.04
FROM debian:latest
FROM alpine:3.18 - שם של אימג' מוכן:FROM python:3.12FROM node:20
4.איך לקבוע את התיקייה שבתוכה ירוצו הפקודות – WORKDIR
המטרה של WORKDIR
היא מאוד פשוטה:
במקום לכתוב בכל פקודה נתיב מלא לתיקייה מסוימת, אתם פשוט אומרים למערכת מראש מאיפה לרוץ.
לדוגמה, נניח שאתם רוצים להריץ פקודה מתוך תיקייה בשם lev3
, שנמצאת בתוך עוד שתי תתי-תיקיות.
תחשבו כמה מסורבל היה כל פעם לכתוב את כל הנתיב המלא – זה היה יוצא ארוך ומעייף.
באמצעות WORKDIR
, אתם יכולים גם ליצור את כל התיקיות בדרך, וגם להיכנס ישירות לתיקייה שאתם צריכים.
משם תוכלו להפעיל פקודות או סקריפטים בקלות, למשל להפעיל סקריפט בשם test1.sh
בלי צורך לכתוב כל פעם את כל הנתיב.
נגיד ואני צריך להעתיק את הקובץ lev1.txt לתוך תיקייה בשם lev5 בקונטיינר, אשתמש ב copy בקובץ:
חשוב לזכור - בשביל שהמערכת תעתיק את lev1.txt לתוך הקונטיינר, הקובץ lev1.txt חייב להיות באותו המקום עם ה dockerfile.6.איך להריץ פקודות במהלך הבנייה של ה-Image – RUN
7. איך להגדיר מה הקונטיינר יעשה כשהוא יתחיל לרוץ – CMD (כמו AUTOSTART בוינדוס)
- HTOP
- IFCONIFG
- ping
- ls-l
8.איך לציין איזה פורט האפליקציה שלנו תשתמש בו – EXPOSE
9. איך להריץ את הקוד תחת משתמש רגיל ולא תחת - Root
10) איך לבדוק אם הקונטיינר באמת חי ופועל כמו שצריך – HEALTHCHECK
נניח שאתם מריצים אפליקציה שהיא שרת WEB, ופתאום יש תקלות.
היה נחמד אם אפשר היה לדעת בזמן אמת מה קורה, נכון?
בדיוק בשביל זה יש את HEALTHCHECK.
הוא אמנם לא מציג לוגים מפורטים, אבל הוא מאפשר לדעת אם משהו השתבש, ומסמן שהקונטיינר לא תקין (
unhealthy
).להלן הפקודה עם ההסברים של הפרמטרים:
- --interval=TIME - כל כמה זמן לבצע בדיקה. - 30 שניות (ברירת מחדל 30 שניות)
- --timeout=TIME - כמה זמן לחכות מקסימום לתוצאה של בדיקה אחת. - 30 שניות (ברירת מחדל 30 שניות)
- --start-period=TIME - זמן חסד בהתחלה – כמה זמן לתת לקונטיינר "להתחמם" לפני שבודקים. - 0 שניות (ברירת מחדל 0 שניות)
- --retries=3 - אחרי כמה כישלונות רצופים ייחשב שהקונטיינר unhealthy. - 3 (ברירת מחדל 3 נסיונות)
דברים חשובים על HEALTHCHECK:
-
HEALTHCHECK הוא אופציונלי.
לא חייבים לשים אותו בכל קונטיינר. אם לא שמתם, דוקר פשוט יחשוב שהקונטיינר תמיד תקין (healthy). -
HEALTHCHECK עובד רק על קונטיינרים חיים.
אם הקונטיינר כבר נפל (Exited), אין בדיקה. HEALTHCHECK רץ רק על קונטיינר שמצבו running. -
סטטוסים אפשריים לקונטיינר אחרי HEALTHCHECK:
starting – בזמן תקופת החסד (start-period).
healthy – הבדיקות מצליחות.
unhealthy – יותר מדי בדיקות נכשלו.
none – אין בכלל הגדרת HEALTHCHECK. -
HEALTHCHECK לא מתקן שום דבר בעצמו.
הוא רק בודק ומסמן מצב (healthy או unhealthy). אם קונטיינר unhealthy – הוא לא ייעצר ולא יאתחל לבד (אלא אם תוסיפו מערכת חיצונית שתטפל בזה). -
HEALTHCHECK משפיע על מערכות ניהול.
למשל: Kubernetes או Docker Swarm יכולות להסתמך על סטטוס unhealthy ולהחליף קונטיינר אוטומטית. -
HEALTHCHECK מוסיף עומס קטן מאוד.
כל בדיקה היא עוד פעולה שהקונטיינר צריך לבצע. אם מגדירים interval קצר מאוד, זה יכול להכביד מעט על הקונטיינר.
11. איך לבנות אימג' בדוקר - Docker Build.
לאחר שבעצם יצרנו את הקובץ, ושמנו אותו בתיקייה שבה יש את כל הקבצים שאנחנו צריכים (במידה וצריך להעתיק קבצים לתוך הקונטיינר וכד'), נעבור ליצירת ה Image שלנו:
- הסינטקס: docker build -t image-name path
- במידה ואנחנו בתוך התיקייה עצמה - . docker build -t Image_Name
- במידה ו Docker file נמצא במקום אחר: docker build -t image_name /full/path/to/folder
- "." - סימן הנקודה בסוף מסמן את התיקייה הנוכחית שאנחנו נמצאים בה
- "t-" - מסמן "tag" זאת אומרת שאנחנו יכולים לתת לו שם - וגירסה אם רוצים, לא חובה אבל כדאי למען הסדר הטוב.
חשוב מאוד לשים לב שבתוך התיקייה שבה נמצא קובץ ה-Dockerfile לא יהיו קבצים מיותרים.
ברגע שמתחילים לבנות (docker build
), דוקר סורק את כל הקבצים בתיקייה ומכניס אותם אוטומטית לתהליך הבנייה – גם את מה שצריך וגם את מה שלא.
אם במקרה השארתם שם, למשל, סרטון של 3 גיגה מהבר מצווה של החתול שלכם – הקובץ הזה ייכנס לבנייה!
הוא לא יפגע באימג', אבל:
-
האימג' יהיה הרבה יותר גדול,
-
תהליך הבנייה יהיה יותר איטי.
לכן תמיד חשוב לסדר מראש את התיקייה, במידה ואנחנו מבולגנים ועדיין רוצים לשמור את הכל באותה תיקייה בדיוק בשביל זה יש את הסעיף הבא..
להלן דוגמא לבניית אימג' מ docker file שכתבתי -
התחלת התהליך:
ובסיום נוכל לראות שהכל בסדר עם כל התהליך שהמערכת עשתה:
נבדוק שהאימג' באמת קיים בעזרת docker images:
וניתן לראות שהאימג' קיים, עכשיו אפשר בלי בעיה להריץ את הקונטיינר, וזה מה שאנחנו נעשה ונבדוק שכל מה שכתבנו בתוך ה docker file באמת נמצא בתוך הקונטיינר שיצרנו.
נריץ את הקונטיינר ונתחבר אליו בעזרת:
12. איך להתעלם מקבצים\תיקיות בניה של אימג'? - docker ignore
מידה ויש קבצים או תיקיות שאנחנו לא רוצים שייכנסו אל תוך ה-Image,
ניצור קובץ בשם .dockerignore
(שימו לב – עם נקודה בהתחלה).
דוקר מחפש את הקובץ הזה בזמן תהליך הבנייה.
אם הקובץ לא יתחיל בנקודה (כלומר ייקרא סתם dockerignore
),
דוקר לא תזהה אותו ולא תשתמש בו בכלל.
בתוך הקובץ .dockerignore
נרשום את כל הקבצים או התיקיות שאנחנו רוצים שדוקר יתעלם מהם.
איך רושמים נכון?
-
אם נרצה שדוקר יתעלם מתיקייה, נרשום את שם התיקייה עם
/
בסוף. -
אם נרצה שדוקר יתעלם מקובץ, פשוט נרשום את שם הקובץ כולל הסיומת.