29/04/2025

מדריך דוקר למתחילים בעברית חלק 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.

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

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


אין תגובות:

הוסף רשומת תגובה

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

תודה :)