‏הצגת רשומות עם תוויות דוקר למתחילים. הצג את כל הרשומות
‏הצגת רשומות עם תוויות דוקר למתחילים. הצג את כל הרשומות

30/05/2025

מדריך דוקר למתחילים בעברית – חלק 2 - פקודות בסיסיות לעבודה עם קונטיינרים ואימג'ים

 



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


לפני שנרוץ להריץ פקודות, אני רוצה להזכיר לכם שתי מושגים חשובים, מה זה "Image" ומה זה "Container"?

"Image" = קובץ תבנית שמכיל מערכת + קבצים מוכנים להרצה, אפשר לקרוא לזה "מתכון" למערכת ההפעלה (מה צריך, כמה צריך איך צריך ומזה נוצרת מערכת הפעלה.

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


להלן הסעיפים שנעבור עליהם במדריך זה:

1) בדיקת מידע כללי על המערכת - docker info

2) יצירה, הרצה של קונטיינר, התחברות לתוך קונטיינר (עם הפרמטרים it- ו ai- ו d-) - docker run 

3) הצגת מידע על קונטיינרים רצים כרגע במערכת - docker ps

4) הצגת מידע על כל הקונטיינרים שיש כולל אלה שלא רצים - docker ps -a

5) איך לעצור קונטיינר? - docker stop

6) איך "להקפיא" קונטיינר בדוקר? - docker pause

7) איך להפעיל קונטיינר שכבר עצרנו? - docker start

8) איך למחוק קונטיינר? - docker rm

9) איך למחוק  "docker rmi  - ?"Image

10) איך להציג את כל ה Imagים הקיימים לנו במערכת? - docker images

11) איך להוריד Image למחשב בלי להפעיל אותו? - docker pull


1. בדיקת מידע כללי על המערכת - docker info

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



2. יצירה והרצה של קונטיינר - docker run


במידה ואנחנו נרצה להריץ איזשהו קונטיינר, נריץ את הפקודה docker run, במידה ואין IMAGE של מה שאנחנו צריכים במערכת שלנו, Docker ילך ל "Docker hub" (מאגר עולמי של אימג'ים), ויוריד אותו (יבצע פעולת Pull)  למחשב, לאחר מכן יבנה מזה קונטיינר, ויריץ את מה שצריך (סרוויס, סקריפט, פקודה וכד') ולאחר מכן "יכבה" ובעצם יצא מהקונטיינר, לכן חשוב להבין מה בדיוק אתם מבצעים, לצורך הדגמה אנחנו נעבוד עם קונטיינר ששמו Alpine (קונטיינר קטן מאוד שמעולה לתרגולים).

מאחר ואין לכם את הקונטיינר על המחשב, נריץ את הפקודה docker run alpine ונראה כיצד המערכת מחפשת את ה Image הזה על המחשב שלכם, מאחר ואין לכם, היא תתחיל להוריד אותו.

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

2.א סתם להוריד ולהריץ אותו בלי שנוכל לעשות משהו - שזה בדיוק מה שתעשה הפקודה docker run alpine ובעצם לאחר שנריץ את הפקודה, הדוקר יוריד את ה IMAGE למחשב שלנו, יפעיל ויכבה אותו ואז הוא יהיה בסטטוס Exited.

2.ב בשביל שנוכל לראות שהוא עשה משהו -  אנחנו ניתן לו פקודה לבצע, לדוגמא להגיד "Hello from Alpine".

נעשה את זה בעזרת הפקודה: "docker run alpine echo "Hello from Alpine.



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

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

docker run -it alpine sh
(בתוך alpine אין BASH (סביבת פקודה של לינוקס) יש שם SH, לכן כתבתי SH בסוף)



וניתן לראות את זה שאני בשורת הפקודה, והרצתי את הפקודה ls.

להלן הפרמטרים שאפשר להשתמש במקרה הזה והפרוש שלהם:
  • "i" - שהוא בעצם "Interactive" ובעצם בצורה הזאת ניתן להקליד דברים לתוך הקונטיינר - הבעיה שלא רואים תגובה.
  • "t" - שהוא בעצם "Terminal" - יפתח לכם מסך עם שורת פקודה בלי שתוכלו להקליד שום דבר, לכן צריך לשלב את שתיהם.
  • "a" - שהוא בעצם "Attach" - ברגע שהרצתם פקודה והקונטיינר במצב Exited (שזה בעצם "כבוי"), אין אפשרות להתחבר אליו עם it-, ולכן צריך להתחבר עם ai- (אנחנו נראה את זה בהמשך)


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

במידה ובוצע הפעלה מחדש למחשב, נרצה שהקונטיינר שלנו יעלה לבד, לצורך כך נשתמש בפרמטר "restart":

docker run -d --name alpaka_restart --restart=always alpine

בפרמטר הזה צריך להשתמש בתהליך הרצת הקונטיינר, בנוסף אם לא תתנו לקונטיינר שום פקודה או פעולה שהוא צריך לעשות ללא הפסקה, בסוף הפעולה הזאת הקונטיינר פשוט "יכבה" לכן ניתן להוסיף משהו בסגנון הזה "tail -f /dev/null" הפקודה הזאת לא עושה שום דבר מיוחד, רק גורמת לקונטיינר להישאר חי, אם מחברים את הכל זה נראה כך:

docker run -d --name alpaka_restart --restart=always alpine tail -f /dev/null


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

במידה ונרצה לשנות את "מדניות" ההפעלה מחדש נשתמש ב docker update:

docker update --restart no container_name

(Docker update - יודע לעשות עוד הרבה דברים, אנחנו נלמד עליו בהרחבה בחלק 4)

2.ד האם אפשר לקרוא לקונטיינר בכל שם שבא לנו?

התשובה היא כן, בעזרת הפרמטר name-- ואני אשתמש בו כאן

אני אריץ את זה בכל הצורות בשביל שתוכלו לראות את ההבדלים, נתחיל: docker run --name alpaka_its_cool alpine:



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


מה שקורה מאחורי הקלעים, ביקשנו מדוקר להוריד את הקונטיינר Alpine לקרוא לו בשם "Alpaka_its_cool" (כן יש לי קטע עם אלפקות, לא יודע למה), להפעיל בתוך הקונטיינר שורת פקודה ולהציג לנו במסך את המשפט:
"!LeiderTech.co.il are the best" (כמובן שאני אובייקטיבי לחלוטין כן... 🤣).

2.ה איך לעבוד על קונטיינר בדוקר?

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

2.ו נריץ את הפקודה: docker run -it --name alpaka_its_cool alpine sh (ה SH בסוף זאת שורת פקודה "מצומצמת" בתוך Alpine).

נוכל לראות שאנחנו בתוך שורת פקודה, בתוך הקונטיינר:


בעצם כאן נוכל לבצע את כלל הפקודות שניתן לבצע בתוך לינוקס כמה דוגמאות:


בשביל לצאת, נריץ את exit ונחזור למכונה הרגילה שלנו:



2.א.א) איך להתחבר לקונטיינר אחרי שכבר הורדנו אותו בדוקר?

במקרה שלנו בעצם ביצענו פקודה ויצאנו מהדוקר, אם נבדוק את הסטטוס שלו (אנחנו נלמד לעשות את זה בהמשך), נקבל שהוא במצב Exited, שזה בעצם סוג של "מכובה" (במקרה הזה, כי לא נתנו לו לרוץ ולבצע פעולות כאלה ואחרות), לכן בשביל להתחבר אליו, צריך להתחיל אותו שוב, נעשה את זה בעזרת הפקודה הזאת: 
docker start -ai alpaka_its_cool

ונוכל לראות שאנחנו שוב בתוך שורת הפקודה בקונטיינר:


2.א.ב) איך יוצרים קונטיינר שירוץ ברקע?

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

 docker run -d --name leidertech alpine tail -f /dev/null

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



עכשיו ננסה להריץ את אותה הפקודה בלי d-:

ובעצם עכשיו אנחנו "תקועים" עם פקודת הרצה של הקונטיינר ולא יכולים לעשות כלום



בשביל לצאת מהמצב הזה נלחץ על ctrl+c (לפעמים צריך כמה פעמים ברצף) ואז נחזור לשורת הפקודה שלנו:


הקונטיינר עצמו ימשיך לרוץ ברקע

3.הצגת מידע על קונטיינרים רצים כרגע במערכת בדוקר


בשביל להציג מידע על הקונטיינרים הרצים לנו במערכת נריץ את docker ps:


הפרוש של העמודות: 
  • CONTAINER ID - המזהה של הקונטיינר
  • IMAGE - מה שם האימג' שירד מדוקר האב (במקרה שלנו זה משם)
  • COMMAND  - מה בעצם כרגע מבצע הקונטיינר - במקרה הזה הוא הפקודה שרצה עכשיו
  • CREATED - מתי נוצר הקונטיינר?
  • STATUS - מה המצב שלו? רץ, לא רץ?
  • PORTS - האם יש הפניית פורטים (נלמד על זה בחלק 4)
  • NAMES - מה השם של הקונטיינר? (האם ניתן לתת שם שאנחנו רוצים? כן אני אראה בהמשך)

3.א איך להציג רק עמודות ספציפיות עם docker ps?


כפי שניתן לראות, נוכל להציג את הקונטיינר שרץ לנו עכשיו במערכת, עכשיו שאלת השאלות, האם אני יכול לבחור אילו עמודות אני רוצה להציג, התשובה היא כן, בעזרת הפרמטר format--, הסינטקס קצת מעצבן, אבל דיי ברור האמת, בדוגמא הבאה אני אבחר להציג רק כמה עמודות:
"docker ps --format "table {{.Image}}\t{{.Command}}\t{{.Status}}\t{{.Names}}



כפי שניתן לראות העמודות הן בהתאם, להלן כלל העמודות שניתן להציג:
{{.ID}}מזהה הקונטיינר
{{.Image}}שם ה־image
{{.Command}}הפקודה שהורצה
{{.CreatedAt}}מתי נוצר הקונטיינר
{{.RunningFor}}כמה זמן הוא רץ
{{.Status}}סטטוס נוכחי (Up/Exited)
{{.Ports}}הפורטים שנפתחו
{{.Names}}השם של הקונטיינר


4. הצגת מידע על כל הקונטיינרים שיש כולל אלה שלא רצים בדוקר


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


לצורך דוגמא נציג רק את אלה שהם בסטטוס EXITED, הפקודה: "docker ps -a --filter "status=exited


ניתן להשתמש בכל הפרמטרים הללו:
--all, -a        מציג את כל הקונטיינרים, גם כאלה שכבר נעצרו  
--filter, -f     מסנן תוצאות לפי תנאי (למשל לפי סטטוס או שם)  
--format         מציג רק את העמודות שאתה רוצה, בעיצוב שאתה מגדיר  
--last, -n       מציג רק את הקונטיינרים האחרונים, לפי מספר  
--latest, -l     מציג רק את הקונטיינר האחרון שנוצר  
--no-trunc       מונע קיצוץ של טקסטים ארוכים (כמו מזהים)  
--quiet, -q      מציג רק את מזהי הקונטיינרים (Container IDs) בלי מידע נוסף  
--size, -s       מציג מידע על גודל הדיסק שכל קונטיינר תופס  

5. איך לעצור קונטיינר בדוקר?


לצורך עצירת קונטיינר נשתמש בפקודה docker stop, לצורך דוגמא, אני מריץ כרגע 5 קונטיינרים:


אני אעצור את test1, הפקודה: docker stop test1, נקבל תגובה "test1" , שזה אומר שהקונטיינר נעצר:


לאחר מכן נריץ את docker ps -a בשביל לראות את כל הקונטיינרים שלנו, ונראה ש test1 הוא Exited:



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


התשובה היא כן, בצורה הבאה: docker stop test2 test3 test4, קיבלנו שוב את שמות הקונטיינרים שעצרנו, זאת אומרת שהכל בסדר:


שוב נריץ את docker ps -a, ונראה שהם כולם במצב Exited:


5.ב איך לתזמן כיבוי של קונטיינר בדוקר?


ניתן לשלב את הפרמטר t- ולאחר מכן כמה שניות ואת שם הקונטיינר שאנחנו רוצים לעצור בצורה הבא:

docker stop -t 3 container_name

מה שיקרה, זה שלאחר 3 שניות הקונטיינר יקבל פקודת כיבוי.

5.ג איך לעצור ולמחוק קונטיינר בפקודה אחת בדוקר?


נגיד ויש לנו קונטיינר שאנחנו לא נצטרך אותו, יש אפשרות לבצע עצירה ואז מחיקה, בעזרת הדגל f- (בכוח - force)
לצורך דוגמא יצרתי קונטיינר בשם test83 שאני לא צריך אותו יותר, אריץ פקודה שתעצור ותמחק את הקונטיינר:


נריץ את הפקודה: docker rm -f test83

קיבלנו תגובה מדוקר וניתן לראות שהוא לא מופיע יותר ברשימה:





6. איך "להקפיא" קונטיינר בדוקר או בעצם לעשות לו Pause?


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

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

ביצוע "הקפאה" מתבצע בעזרת הפקודה  docker pause container_name:



ניתן לראות שהוא עצר:



בשביל "להוציא" אותו מהקפאה נריץ את הפקודה : docker unpause container_name


ונראה שהקונטיינר חזר לפעול:



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

docker pause cont1 cont2 cont3

ו"להפשיר" על ידי docker unpause cont1 cont2 cont3


7. איך להריץ קונטיינר שעצרנו (שעשינו לו Stop) בדוקר?

 
בשביל להפעיל קונטיינר נשתמש בפקודה docker start  ושם הקונטיינר בסוף - docker start test1:



נריץ את docker ps -a (אפשר גם בלי a-) ונראה שהוא רץ:


7.א האם אפשר להפעיל כמה קונטיינרים ביחד בדוקר?


כן, ניתן להפעיל כמה קונטיינרים ביחד, בדומה לפקודה הקודמת עם STOP, נשתמש הפעם ב START:

docker start test1 test2 test3



נריץ את docker ps -a (ניתן גם בלי a-) בשביל לבדוק את המצב:



ניתן לראות שכולם למעלה.

לידע כללי מה קורה מאחורי הקלעים ברגע שמריצים את -  docker start, הוא לא יבצע שום דבר חדש, אלה ימשיך להריץ את הדבר האחרון שנתנו לו, פקודה, שירות תוכנה וכד', בעמודה "Command" ניתן לראות מה אנחנו מריצים, כאן נתתי לו סתם דוגמא שתרוץ בשביל שהוא לא יפסיק.


8. איך למחוק קונטיינר בדוקר?


מחיקת קונטיינר מתבצע בעזרת הפקודה docker rm continer_name, אבל אי אפשר סתם למחוק אותו,
כי אי אפשר סתם ככה למחוק קונטיינר, צריך קודם לעצור אותו ורק לאחר מכן למחוק אותו, אבל מאחר ואנחנו אנשי מחשוב ואני לא אוהב לבצע כל דבר 50 פעם, אנחנו נשלב שתי פקודות בתוך פקודה אחת בעזרת הסימן "&" אם אנחנו נכתוב את הסימן הזה פעמיים "&&", המשמעות של הסימן הזה בלינוקס, הוא "רק אם הצלחת להריץ את הפקודה הראשונה ולא התפוצץ המחשב והכל בסדר, תריץ את השניה", אז נריץ את הפקודה בצורה הזאת: docker stop test1 && docker rm test1

לא קיבלתי שום שגיאה, אלה פלט תקין:


ונבדוק מה רץ לנו עכשיו עם docker ps -a (אפשר גם בלי a-):



ניתן לראות שאין את test1 יותר (בעמודה מצד ימין).

9. איך למחוק Image בדוקר?


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

1) לעצור את הקונטיינר במידה והוא רץ, 2) למחוק את הקונטיינר, 3) למחוק את ה IMAGE, ניתן לבצע את זה בשלוש 

פקודות שניתן להריץ אחת אחרי השניה:
1) לעצור את הקונטיינר -  docker stop container_name
2) למחוק את הקונטיינר- docker rm container_name
3) למחוק את האימג' - docker rmi image_name

אבל זה המון מדי לכתוב ולכן אנחנו נאגד את כל זה לפקודה אחת ארוכה בעזרת הסימן שראינו בסעיף הקודם "&&"

docker stop test1 && docker rm test1 && docker rmi alpine

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



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

docker stop $(docker ps -q) && docker rm $(docker ps -a -q) && docker rmi $(docker images -q)

❗ לא להריץ את הפקודה הזאת בשרת בסביבה אמיתית– היא מוחקת הכל ❗



ועכשיו אפשר לראות שהכל נמחק:


להלן פירוש של הפקודה:
  • docker stop $(docker ps -q) - עצר את כל הקונטיינרים.
  • docker rm $(docker ps -a -q) - מחק את כל הקונטיינרים כולל אלה שכבר היו במצב EXITED.
  • docker rmi $(docker images -q) - מחק את כל האימג'ים.

10. איך לקבל מידע על Image בדוקר?


בשביל לקבל מידע ולהבין אילו Imagים יש לנו במערכת נריץ את הפקודה docker images:

ניתן להשתמש בפרמטרים הללו:
  • --all, -a  - מציג גם תמונות ביניים (intermediate images) שלא מוצגות כברירת מחדל
  • --digests  - מציג גם את ה־digest של ה־image (מזהה ייחודי נוסף)
  • --filter, -f  - מסנן לפי תנאי מסוים (כמו לפי שם או גודל) - פה הסינטקס קצת קשה, אז הינה דוגמא:

    סינטקס לדוגמא: "*docker images -f "reference=alpine

  • -- format  -  מציג את הפלט לפי תבנית מותאמת אישית (כמו ב־docker ps) - גם פה הסינטקס קצת קשה,
    אז הינה דוגמא:"docker images --format "{{.Repository}}:{{.Tag}} ({{.Size}})

  • --no-trunc  - מציג את כל המזהים (image ID, command...) במלואם, בלי קיצורים

  • --quiet, -q  -  מציג רק את מזהי ה־image (IMAGE ID), בלי טבלה

11. איך להוריד Image של דוקר למחשב בלי להפעיל אותו?


הורדה של Image מתבצעת בעזרת הפקודה docker pull what_to_pull, מה שיקרה בפועל, זה שהמערכת פשוט תוריד להם אימג' הכי עדכני שיש למערכת שהציינתם למחשב וזהו, ורק אם תרצו לעשות איתו משהו תצטרכו להריץ אותו עם docker run כפי שלמדנו בסעיף על docker run.



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

שימו לב, נריץ את docker images ונקבל חמישה אימג'ים:



ורצים לנו 4 קונטיינרים:



11.א איך לבחור איזו גירסת Image להוריד?


בדוקר יש פרמטר שנקרא tag שהוא בעצם אחראי על להגיד למערכת, איזו גירסה אנחנו רוצים להוריד, ואנחנו עכשיו נשתמש בו בשביל להוריד 3 גרסאות שונות של Image, הסינטקס: docker pull image:tag:



כאן ניתן לראות את ההבדלים בין הגרסאות השונות של האימג'ים:



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

-a, --all-tags - מושך את כל ה־tags (כל הגרסאות) של ה־image
--platform - מושך גרסה לארכיטקטורה מסוימת (למשל linux/amd64)
-q, --quiet - הורדה בלי להציג התקדמות במסך
--disable-content-trust - מבטל אימות חתימות דיגיטליות (ברירת מחדל: true)

עד כאן להפעם,
המייל שלי לכל שאלה: levl@leidertech.co.il

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

חלק 3 במדריך דוקר: כאן

כל החלקים של המדריך על דוקר: כאן

מדריך PowerShell למתחילים: כאן


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


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 במדריך דוקר: כאן

כל החלקים של המדריך על דוקר: כאן

מדריך PowerShell למתחילים: כאן


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