29/04/2025

מדריך דוקר למתחילים בעברית חלק 5 - איך כותבים DockerFile?


 
אהלן וברוכים הבאים לחלק החמישי במדריך "דוקר למתחילים בעברית"!

בפרק הזה נעשה קפיצת מדרגה ונלמד לבנות בעצמנו אימג'ים מדויקים לפי הצרכים שלנו, באמצעות קובץ מיוחד בשם 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?

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

1.ב מה מכיל Docker file?
הקובץ הזה מכיל את הפרטים הבאים (סך הכל יש 17 סעיפים):
  • מאיזה בסיס להתחיל? זאת אומרת על איזו מערכת הפעלה נריץ את הקונטיינר? (למשל: 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 ועוד. 


(לידע כללי - על Docker compose אנחנו נדבר בחלק 6)

2. המבנה הכללי של Dockerfile

תכלס, הדבר היחיד שחובה כשיוצרים אימג', זה להשתמש רק בפקודה from, שבעצם המשמעות שלה זה "מאיזה סוג של מערכת הפעלה לבנות את האימג'" - יענו מה אתה רוצה להתקין? לאחר מכן אפשר להוסיף עוד דברים (אנחנו נעבור על רוב הדברים שאפשר לשים בקובץ Docker file).

ה docker file נראה ככה:





וזהו, מה שזה יעשה, זה להוריד אימג' מבוסס אובונטו, לאחר מכן יבצע התקנה של דברים: apt update && apt install -y htop, ואז בסוף יריץ את הפקודה htop (מי שלא יודע מה זה, יש לנו הסבר על זה במדריך לינוקס למתחילים: כאן).

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

לכן במקרה שלי יצרתי את התיקיות שאני רוצה בנתיב שאני רוצה, לאחר מכן יצרתי עם nano קובץ בשם Dockerfile, כדי מאוד להשתמש בקובץ עם אות גדולה), קודם כל זה מוסכמות, דבר שני ברגע שכותבים docker build, המערכת אוט' מחפשת את הקובץ Dockerfile עם אות גדולה, וכידוע, לינוקס מסתכל על אותיות קטנות וגדולות, מבחינתו זה לא אותו דבר.


3.איך לקבוע את הבסיס שעליו נבנה את האימג' – FROM

כשרוצים להשתמש ב "from" ניתן לבחור כמה אופציות של בניה:

  • שם של מערכת הפעלה:
    FROM ubuntu:20.04
    FROM debian:latest
    FROM alpine:3.18

  • שם של אימג' מוכן:
    FROM python:3.12
    FROM node:20

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

4.איך לקבוע את התיקייה שבתוכה ירוצו הפקודות – WORKDIR

המטרה של WORKDIR היא מאוד פשוטה:
במקום לכתוב בכל פקודה נתיב מלא לתיקייה מסוימת, אתם פשוט אומרים למערכת מראש מאיפה לרוץ.

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

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





5.איך להעתיק קבצים מהמחשב שלנו לתוך האימג'– COPY

נגיד ואני צריך להעתיק את הקובץ lev1.txt לתוך תיקייה בשם lev5 בקונטיינר, אשתמש ב copy בקובץ:



חשוב לזכור - בשביל שהמערכת תעתיק את lev1.txt לתוך הקונטיינר, הקובץ lev1.txt חייב להיות באותו המקום עם ה dockerfile.

6.איך להריץ פקודות במהלך הבנייה של ה-Image – RUN

לצורך הרצת פקודה נשתמש בפרמטר RUN ב Docker file כפי שראינו בדוגמא הקודמת:



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

ניתן גם לשרשר פקודות: RUN apt update && apt install -y nginx curl

7. איך להגדיר מה הקונטיינר יעשה כשהוא יתחיל לרוץ – CMD (כמו AUTOSTART בוינדוס)

במידה ואני רוצה שלאחר שהקונטיינר נבנה, הוא יריץ פקודות אוט' אני אוסיף את הפרמטר CMD, אך יש לו הגבלות, הוא יכול להריץ רק פקודה אחת בכל פעם, זאת אומרת אי אפשר לרשום לדוגמא:
"CMD "htop
"CMD "ifconfig

כי מבחינת המערכת היא תריץ רק את ה CMD האחרון, לכן יש צורך בשרשור של פקודות, נגיד ואני רוצה להריץ:
  • HTOP
  • IFCONIFG
  • ping
  • ls-l
בשביל שזה ירוץ אני צריך להגיד למערכת "תריץ ב BASH את הפקודות הללו", לכן לצורך זה נשתמש בסינטקס "&&" שהוא שרשור של פקודות (רק אם הראשונה הצליחה, תריץ את הבאה ניתן להשתמש בכל צורת שרשור, אני בחרתי דווקא את זה כי אני רגיל וזה עניין של בטיחות) בצורה הזאת:

CMD ["bash", "-c", "htop && ifconfig && ping -c 4 8.8.8.8 && ls -l"]

בעיקרון הדבר היחיד שלא ברור כאן זה "c-" והמשמעות שלו ה "Command" זאת אומרת "bash -command" ואז כל השאר.




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

CMD ["python3", "app.py"]

8.איך לציין איזה פורט האפליקציה שלנו תשתמש בו – EXPOSE

ברגע שיש צורך להגדיר פורטים לקונטיינר (8080, 443) וכד', נשתמש ב EXPOSE, בעצם זה אומר לדוקר, תשמע תפתח בקונטיינר את הפורטים הנ"ל, את התהליך של חיבור הפורטים מהקונטיינר למחשב שלנו, נעשה במהלך docker run.

מבחינת הסדר, את החלק של EXPOSE, נכתוב לפני ה CMD.

9. איך להריץ את הקוד תחת משתמש רגיל ולא תחת - Root

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

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

לצורך כך נשתמש בפרמטר "USER" ונרשום את שם משתמש שנרצה ליצור USER leidertech1



10) איך לבדוק אם הקונטיינר באמת חי ופועל כמו שצריך – HEALTHCHECK


נניח שאתם מריצים אפליקציה שהיא שרת WEB, ופתאום יש תקלות.
היה נחמד אם אפשר היה לדעת בזמן אמת מה קורה, נכון?
בדיוק בשביל זה יש את HEALTHCHECK.
הוא אמנם לא מציג לוגים מפורטים, אבל הוא מאפשר לדעת אם משהו השתבש, ומסמן שהקונטיינר לא תקין (unhealthy).

בפקודה הזאת יש כמה וכמה פרמטרים חשובים:

להלן הפקודה עם ההסברים של הפרמטרים:

HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3   CMD ping -c 1 localhost || exit 1

  • --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 באמת נמצא בתוך הקונטיינר שיצרנו.

נריץ את הקונטיינר ונתחבר אליו בעזרת:

docker run -it --name leidertech_test_container leidertech_test_image bash

וניתן לראות ישר שאנחנו במשתמש שיצרנו בתוך התיקייה שיצרנו גם כן בתוך ה docker file:


עכשיו נבדוק מה יש בתיקייה שאנחנו נמצאים בה:


כמו שכתבנו ב docker file - יש קובץ test1.sh:


ונבדוק מה יש בתוך ה test1.sh (נבדוק שזה באמת הקובץ שלנו):



כפי שניתן לראות הכל כפי שיצרנו בקובץ docker file.

ומה קורה עם רוצים ליצור 6 אימג'ים או 20? - אז בשביל זה יש דבר כזה שנקרא docker-compose - עליו נלמד בפרק הבא.

12. איך להתעלם מקבצים\תיקיות בניה של אימג'? - docker ignore

מידה ויש קבצים או תיקיות שאנחנו לא רוצים שייכנסו אל תוך ה-Image,
ניצור קובץ בשם .dockerignore (שימו לב – עם נקודה בהתחלה).

דוקר מחפש את הקובץ הזה בזמן תהליך הבנייה.
אם הקובץ לא יתחיל בנקודה (כלומר ייקרא סתם dockerignore),
דוקר לא תזהה אותו ולא תשתמש בו בכלל.

בתוך הקובץ .dockerignore נרשום את כל הקבצים או התיקיות שאנחנו רוצים שדוקר יתעלם מהם.

איך רושמים נכון?

  • אם נרצה שדוקר יתעלם מתיקייה, נרשום את שם התיקייה עם / בסוף.

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

notes.txt
videos/
logs/


וזהו, פשוט נשמור את הקובץ, ואז בהרצה, המערכת תתעלם מכל מה שכתבנו פה.

זה הכל להפעם

המייל שלי לכל שאלה levl@leidertech.co.il.

מדריך לינוקס למתחילים: כאן

להלן מדריך מצולם:


מדריך דוקר למתחילים בעברית חלק 6 – מה זה Docker Compose ואיך משתמשים בו?






אהלן לכולם, וברוכים הבאים לחלק השישי והאחרון במדריך "דוקר למתחילים בעברית"!

בפרק הזה נכיר את אחד הכלים הכי חשובים ואהובים על כל מי שעובד עם Docker – כלי בשם Docker Compose.
נלמד איך אפשר להפעיל כמה קונטיינרים ביחד בצורה חכמה דרך קובץ אחד, איך לבנות פרויקטים שלמים בצורה אוטומטית, לשתף תיקיות ופורטים, לשלב Dockerfile בתוך Compose, לנהל משתנים עם קובץ .env, ולשלוט באיך ומתי קונטיינרים יופעלו מחדש.

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

¿?רגע - לפני שאתם ממשיכים קראתם את חמשת החלקים הראשונים!!!¿?

שימו לב ! לפני שאתם ממשיכים לעבור על החלק האחרון, תעברו על חמשת החלקים הראשונים כדי שתבינו על מה מדובר מאחר ובמקרה של דוקר, חשוב מאוד להבין את המושגים ומה בדיוק אנחנו עושים כי הדברים יכולים להיות מבלבלים.

ניתן לעבור על כל החלקים בעמוד המיועד לדוקר בבלוג: מדריך דוקר למתחילים בעברית - כל החלקים



1) מה זה Docker Compose ולמה להשתמש בו?

2) מה זה קובץ docker-compose.yml ואיך הוא בנוי?

3) איך מריצים פרויקט עם docker compose up?

4) איך מכבים ומנקים פרויקט עם ? docker compose down

5) איך מפעילים כמה שירותים (קונטיינרים)  ביחד?

6) איך מחברים Volume לקונטיינר דרך Compose?

7) איך לפתוח פורטים דרך Compose?

8) איך משלבים Dockerfile בתוך Compose?

9) איך משתמשים בקובץ .env לשמירת משתנים?

10) איך לגרום לקונטיינרים לעלות אוטומטית אחרי קריסה או הפעלה מחדש?



1.מה זה Docker Compose ולמה להשתמש בו?

אז מה זה בעצם Docker Compose?
מדובר על כלי שמאפשר להריץ כמה קונטיינרים ביחד בצורה קלה ופשוטה, בעזרת קובץ אחד – שלרוב נקרא docker-compose.yml, או בקיצור "קובץ יאמל".

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

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

לידע כללי: בתוך docker-compose אפשר להגדיר גם docker file.

2) מה זה קובץ docker-compose.yml ואיך הוא בנוי?

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

יש כמה חלקים בקובץ הזה אבל הינה המרכזיים:
  • version – גרסת הפורמט (לא חייבים לכתוב בכלל)

  • services – כאן מגדירים את כל הקונטיינרים שנרצה להפעיל.

    בתוך כל שירות (service) מגדירים:

  • image – מאיזה אימג' לבנות

  • build – אם רוצים לבנות Image חדש מ-Dockerfile מקומי.

  • ports – אילו פורטים לפתוח

  • volumes – אילו תיקיות לשתף

  • environment – אילו משתנים להעביר

  • depends_on – אם יש תלות בין שירותים

    ועוד פרמטרים לפי הצורך.
אם נשים שם גם build: וגם image: באותו שירות –
Docker יבנה את האימג' מה-Dockerfile ואז ייתן לו שם לפי מה שכתבת באימג'.

להלן דוגמא לקובץ docker-compose:



את הקובץ docker-compose.yaml, כדאי (לא חובה) לשמור באותה התיקייה שבה יש לנו את כל קבצי הפרויקט (docker file, ignore וכד').

כי אם נרצה לבנות אימג' בתוך הקומפוז, אז צריך שהכל יהיה באותה התיקייה.

משהו עם קצת יותר פרמטרים:


טבלת מפתחות נפוצים בקובץ Docker Compose (docker-compose.yml):

מפתח שייך ל... תיאור קצר
version רמה עליונה גרסת הפורמט של הקובץ (למשל: '3.8')
services רמה עליונה רשימת הקונטיינרים שאתה רוצה להרים
networks רמה עליונה הגדרת רשתות מותאמות אישית
volumes רמה עליונה הגדרת Volumes לשיתוף קבצים
configs רמה עליונה (Swarm) קבצי קונפיגורציה למצב swarm
secrets רמה עליונה (Swarm) קבצי סוד לשימוש מאובטח

בתוך כל service

מפתח תיאור קצר
image שם ה־Image שממנו נבנה הקונטיינר
build הגדרות לבניית Image מקובץ Dockerfile
container_name שם מותאם אישית לקונטיינר
command פקודה שתורץ בתוך הקונטיינר
entrypoint פקודת כניסה (לפני command)
environment משתני סביבה (ENV)
env_file קובץ .env חיצוני
volumes חיבור תיקיות בין הקונטיינר למחשב שלך
ports פתיחת פורטים (למשל 80:80)
networks לאיזו רשת הקונטיינר שייך
depends_on אילו שירותים חייבים לרוץ לפניו
tty מדמה מסך (כדי שתוכל להיכנס עם bash)
stdin_open מאפשר לשלוח קלט (למשל מקלדת)
restart מתי להפעיל מחדש את הקונטיינר (למשל always)
healthcheck בדיקת תקינות של הקונטיינר
labels תגים מותאמים (לניהול, סינון וכו')

בתוך networks

מפתח תיאור קצר
driver סוג הרשת (bridge, host, overlay)
external האם הרשת כבר קיימת מחוץ לקובץ
name שם מותאם אישית לרשת
ipam הגדרת טווחי כתובות IP

בתוך volumes

מפתח תיאור קצר
driver סוג ה־Volume (לרוב local)
external האם ה־Volume כבר קיים
name שם מותאם אישית ל־Volume


3. איך מריצים פרויקט עם Docker Compose (docker compose up)?

ראשית ניצור את הקובץ שלנו :




לאחר שיצרנו את הקובץ docker-compose.yaml, שלנו, אנחנו נרצה להריץ אותו, בשביל להריץ נרשום:
docker compose up -d



ונבדוק עכשיו האם הקונטיינרים רצים בעזרת docker ps:


כל הפרמטרים של הפקודה הזאת:
  • -f - לציין נתיב ל Compose אחר במקום ברירת מחדל (docker-compose.yml)
  • דוגמה: docker compose -f my-compose-file.yml up

  • -d - להפעיל את הקונטיינרים ברקע (Detached mode)
  • דוגמה: docker compose up -d

  • --build - לבנות מחדש את ה-Images גם אם קיימים כבר
  • דוגמה: docker compose up --build

  • --force-recreate - להכריח יצירת קונטיינרים חדשים גם אם קיימים קונטיינרים ישנים
  • דוגמה: docker compose up --force-recreate

  • -d --force-recreate - להרים קונטיינרים חדשים בכוח וגם להריץ אותם ברקע
  • דוגמה: docker compose up -d --force-recreate

  • -d --build --force-recreate - גם לבנות את ה-Images מחדש, גם להכריח יצירת קונטיינרים חדשים, וגם להריץ ברקע
  • דוגמה: docker compose up -d --build --force-recreate

  • --remove-orphans - למחוק קונטיינרים "יתומים" שלא מוגדרים יותר בקובץ Compose הנוכחי
  • דוגמה: docker compose up -d --remove-orphans

4. איך מכבים ומנקים פרויקט עם docker compose down?

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

אנחנו נשתמש בזה עכשיו בשביל להוריד את כל הקונטיינרים שהרצנו בסעיף הקודם - נריץ את הפקודה:



וניתן לראות שהכל הוסר כמו שצריך (כולל הרשת שיצרה המערכת) :


פרמטרים שניתן להשתמש בהם עם docker compose down:

  • -v - מוחק גם את ה-Volumes שנוצרו על ידי ה-Compose
  • דוגמה: docker compose down -v

  • --rmi all - מוחק את כל ה-Images שקשורים לפרויקט (גם אלה שנמשכו וגם אלה שנבנו)
  • דוגמה: docker compose down --rmi all

  • --rmi local - מוחק רק את ה-Images שנבנו מקומית (לא את ה-Images שנמשכו מהאינטרנט)
  • דוגמה: docker compose down --rmi local

  • --remove-orphans - מוחק קונטיינרים "יתומים" (קונטיינרים שלא קיימים יותר בקובץ Compose אבל עדיין רצים)
  • דוגמה: docker compose down --remove-orphans

  • --timeout <seconds> - קובע כמה שניות לחכות לפני שהקונטיינרים ייהרגו בכוח
  • דוגמה: docker compose down --timeout 10
כשמבצעים את הפעולה - המערכת לא מוחקת Volume ולא מוחקת את האימג'ים!

5. איך מפעילים כמה שירותים (קונטיינרים) ביחד?

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



ועכשיו נריץ את הבניה של הקונטיינרים:



לאחר שהתהליך הסתיים, נוכל לראות שהכל בסדר:

והקונטיינרים רצים להם ברקע:


6. איך מחברים Volume (משתפים תיקייה מהמחשב לקונטיינר) ב Docker compose?

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


וככה זה נראה בתוך קובץ docker-compose:


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

נמשיך, עכשיו נשאר לבנות את הקונטיינרים:


בוא נראה אילו תיקיות יש לי בתוך Project5:


חיברנו לקונטיינר את התיקייה things_for_project, נציג את התוכן שלה:


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

docker exec -it projetc5-alpaca1-1 bash


וכפי שניתן לראות, התוכן, הוא אותו תוכן, ואני נמצא בתוך הקונטיינר.

7. איך לפתוח פורטים ב Docker Compose?

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



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



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

8.איך משלבים Dockerfile בתוך Docker Compose?

8.א. למה כדאי לשלב docker file בתוך docker compose?

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

2. אוטומציה:
כשמציינים build: ב־docker-compose.yml, מערכת Docker Compose,  בונה את האימג' אוטומטית. יש אפשרות להפעיל הכל עם פקודה אחת (docker compose up), בלי הצורך להריץ docker build בנפרד.

3. שירותים (קונטיינרים) מרובים:
Docker Compose מאפשר להריץ כמה קונטיינרים ביחד עם Dockerfiles מותאמים אישית. כל קונטיינר יכול לקבל את האימג' המתאים לו, עם הגדרות שונות לכל אחד.

4. בנייה ועדכון מהירים:
כל פעם שמתבצע שינוי של ה־Dockerfile, יש אפשרות להריץ docker compose up --build כדי לבנות מחדש את האימג' עם השינויים. אין צורך לנהל Images חיצוניים או לדאוג לעדכונים ידניים.

8.ב. איך בעצם מבצעים את השילוב בפועל?
בשביל לשלב קובץ dockerfile בתוך docker compose, נכתוב את הפרמטר "build" ונציין את הנתיב ל-dockerfile, במידה והקובץ נמצא באותה התיקייה של ה docker-compose, פשוט נכתוב סימן של "נקודה" (כפי שהראינו באחד הסעיפים הקודמים) - הסינטקס : build: path_to_dockerfile_directory


נגיד ואני רוצה לבנות אימג' מתוך docker file שנמצא בתיקיית alpaca שבתוך תיקיית hamburger:


נגיד (ומסיבה לא ברורה בעליל) החלטנו לקרוא ל dockerfile שלנו בשם i_love_alpacot_and_docker ואנחנו רוצים לשלב את זה ב docker-compose, וכל זה ירוץ על קונטיינר בשם shnitzel זה יראה ככה:


9.איך משתמשים בקובץ .env לשמירת משתנים?

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

9.א מה שמים ומה לא שמים בתוך קובץ .env?

נתחיל עם מה כן שמים - כל טקסט פשוט, שאין בו פקודות, לוגיקה או מבנים מסובכים – מותר - לדוגמא:
  • משתנים - age=18
  • סיסמאות - db_pass=123456
  • פורטים - http_port=8080
  • כתובת של שרת - server_name=blublu אפשר לשים גם כתובות - server_ip=192.168.1.1
  • נתיבים למיניהם - path = /Desktop/shnitzel
  • ואם רוצים לראות יותר מידע אודות התהליך מפעילים דיבאג - DEBUG=True
מה לא שמים - אסור לשים פקודות, סקריפטים, מבני נתונים, חישובים או קונפיגורציות מתקדמות לדוגמא:
  •  פקודות דוקר - `docker build -t myapp
  •  פקודות התקנה - `apt update && apt install nginx` 
  •  תכנים של דוקרפייל - `FROM ubuntu:20.04` 
  •  לוגיקה/תנאים - `if [ $PORT -eq 8080 ]; then echo OK; fi` 
  •  מערכים/אובייקטים - `PORTS=[8080,9090]` 
  •  חישובים מתמטיים -`PORT=8000+1` 
  •  הגדרות של Volume או Network - אסור -   `volume_name: myvolume` 
9.ב היכן שמים את הקובץ .env?

הקובץ חייב להיות באותו המקום שבו נמצא ה docker-compose, אחרת המערכת לא תדע להשתמש בו.

9.ג עניין של סודיות

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

10.איך לגרום לקונטיינרים לעלות אוטומטית אחרי קריסה או הפעלה מחדש ב Docker compose?

קורה לכם מצב שבו המחשב פתאום מבצע הפעלה מחדש? כי נתקע, או היתה הפסקת חשמל או שהייתם צריכים ליזום הפעלה מחדש, במצב כזה לא תמיד אנחנו נזכור מה צריך להעלות ומה לא, לכן יש לנו אפשרות (כפי שלמדנו בחלק 2) להוסיף לקומפוז הגדרה של "עליה במצב של הפעלה מחדש", האם להעלות? לא להעלות? רק במצב שבו המחשב נתקע וכד':

נוסיף את הסעיף: "Restart" בתוך הקובץ בצורה הזאת:



להלן כל הפרמטרים שניתן להוסיף:
  • `no` - (ברירת מחדל) – לא מנסה להפעיל מחדש בכלל
  • `always`  - תמיד מנסה להפעיל מחדש – גם אחרי הפעלה מחדש.
  • `on-failure` - יפעיל מחדש רק אם הקונטיינר נפל\קרס (Exited עם קוד שגיאה) 
  • `unless-stopped` - יפעיל מחדש כל עוד לא עצרת אותו בעצמך 

זה הכל להפעם

המייל שלי לכל שאלה levl@leidertech.co.il.

מדריך לינוקס למתחילים: כאן

להלן מדריך מצולם: