‏הצגת רשומות עם תוויות docker run. הצג את כל הרשומות
‏הצגת רשומות עם תוויות docker run. הצג את כל הרשומות

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 למתחילים: כאן


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


מדריך דוקר למתחילים בעברית – חלק 3 - לוגים, פקודות, חיבור תיקיות, פתיחת פורטים וניהול Volumes



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

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

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


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

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

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

 

להלן הסעיפים שנעבור עליהם היום:

1) איך לקבל מידע על קונטיינר בדוקר? - docker inspect

2) איך לבדוק לוגים בקונטיינר של דוקר? - docker logs

3) איך לשנות שם של קונטיינר בדוקר? - docker rename

4) איך להריץ פקודות בתוך קונטיינר שכבר רץ בדוקר? - docker exec

5) איך להעתיק קבצים מהמחשב לקונטיינר וההפך בדוקר? - docker cp

6) עבודה עם Volumes - איך לחבר תיקייה\כונן\אלפקה במחשב שלנו לקונטיינר בדוקר - docker run -v

7) להציג Volumes  בדוקר? - docker volume ls

8) איך למחוק Volume  בדוקר? - docker volume rm

9) איך עושים "סדר פסח" בדוקר ומנקים Imageים שלא בשימוש כבר בדוקר - docker image prune

10) איך לבדוק כמה משאבים צורך כל קונטיינר בדוקר - docker stats

11) תקשורת בדוקר – איך לחבר בין קונטיינרים ולפתוח פורטים בדוקר?


1. איך לקבל מידע על קונטיינר בדוקר? -   docker inspect container_name


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

אם אנחנו נריץ את הפקודה docker inspect test1 נקבל המון מידע בפורמט "json"

לידע כללי,  מה זה json? - זה פורמט פשוט וקריא לאחסון ולהעברת מידע. מאוד נפוץ בשפות תכנות ובעיקר בשימוש עם APIs.

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







יש כאן המון המון מידע מאוד חשוב לדוגמא:

שם הקונטיינר:
test1

מצב:
running (פועל)

תאריך יצירה:
2025-04-17T18:58:50Z

פקודה שרצה בקונטיינר:
tail -f /dev/null

תמונה (Image):
alpine

ID של הקונטיינר:
024ab10866e065d9b9c04ddd28f669df4a580e98d43047bb97df905250c5b7bd

IP פנימי:
172.17.0.2

Gateway:
172.17.0.1

PID של התהליך הראשי:
33705

נתיב הלוג:
/var/lib/docker/containers/024ab10866e065d9b9c04ddd28f669df4a580e98d43047bb97df905250c5b7bd/024ab10866e065d9b9c04ddd28f669df4a580e98d43047bb97df905250c5b7bd-json.log

רשת:
bridge

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

 docker inspect test1 |less

במצב הזה, נקבל בסוף המסך למטה סימן של נקודותיים ":" -





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



אם תנסו לכתוב משהו באות קטנה כאשר בפועל הוא מתחיל באות גדולה, לא תמצאו את מה שאתם צריכים ותקבלו הודעת שגיאה כזאת: Pattern not found  (press RETURN)



בשביל לצאת מהחיפוש ולחזור לשורת הפקודה שלנו, נלחץ על "q":



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

דוגמאות של סינטקס:
  • docker inspect -f '{{.State.Status}}' test1

  •  docker inspect --format '{{.State.Status}}' test1
מאחר וקונטיינר בשם test1 אצלי רץ, אני אקבל את התגובה הרלוונטית: "Running"



1.א. איך להציג שדה ספציפי עם docker inspect?


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

docker inspect --format '{{.State.Status}}' test1

איך בעצם נדע כיצד לגשת ל Status?


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



נגיד ואני רוצה לגשת ל Pid, אני אכתוב: docker inspect --format '{{.State.Pid}}' test1:



בשביל להראות את זה קצת יותר טוב, אני אגש ל Links שהוא הרביעי בנתיב:


הפקודה תראה כך: docker inspect --format '{{.NetworkSettings.Networks.bridge.Links}}' test1


1. NetworkSettings
  2.Networks
    3.bridge
      4.Links

תשימו לב שאחרי "NetworkSettings", "Networks" , "bridge" יש סוגר מסולסל, זאת אומרת הוא "סעיף" שיש לו תתי סעיפים, ניתן לראות את זה על ידי דוגמא של "Name":


לכן גם הגישה אליו תהיה מאוד פשוטה: docker inspect --format '{{.Name}}' test1

כל הפרמטרים (בדוקר הם נקראים Flags אבל אני רגיל לפרמטרים) של docker inspect:

--format - מאפשר לשלוף רק שדות מסוימים מתוך הפלט, בעזרת  (כמו {{.Name}}).
--type - קובע את סוג האובייקט שנרצה לבדוק container, image, network, volume, node.
--size - מציג (רק לקונטיינרים) מוסיף מידע על גודל התוכן של הקונטיינר.
--help - קבלת עזרה לפקודה docker inspect.


2. איך לבדוק לוגים בקונטיינר של דוקר? - docker logs

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

חשוב להבהיר משהו אחד: אנחנו לא מדברים כאן על לוגים של מערכת ההפעלה — כמו ה־Events שאתם אולי מכירים מ־Windows.

מה ש־docker logs מציג זה לא שגיאות מערכת, אלא יותר כמו רישום של פלט שהאפליקציה בתוך הקונטיינר הדפיסה,
זה יכול להיות טקסט שהצגנו למשתמש, שגיאות שהופיעו כשהאפליקציה קרסה, הודעות echo, print, או לוגים שהאפליקציה בחרה להציג החוצה למסך.

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



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

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

docker run -d --name wtf_name alpine sh -c 'echo "container_started" && tail -f /dev/null'

להלן הפירוש של הפקודה (יש כאן דגלים שלמדנו עליהם כבר בפרקים הקודמים):
  • docker run - מריץ קונטיינר חדש
  • -d - מריץ את הקונטיינר ברקע (detached mode)
  • --name mylogger - נותן לקונטיינר שם קבוע: mylogger
  • alpine - זה האימג' שממנה הקונטיינר נבנה – פה Alpine Linux
  • sh -c '...' - מריץ פקודה אחת בתוך shell (שֶל) בתוך הקונטיינר
  • echo "קונטיינר התחיל" - כותב טקסט למסך – וזה נכנס ללוג
  • && - אם הפקודה הראשונה הצליחה → ממשיכים הלאה
  • tail -f /dev/null - פקודה שלא עושה כלום אבל שומרת את הקונטיינר חי

מה ירשם בלוגים?
  • echo-  "משהו" בתוך הפקודה הראשית - מדפיס למסך (פלט של תוכנה) ונשמר בלוג של הקונטיינר
  • שגיאה מתוך התהליך הראשי, שגיאות שנכתבות למסך הראשי – גם הן נשמרות בלוג
  • print() בתוך תוכנה שרצה בקונטיינר - כל הדפסה למסך (מה שנקרא Output) תיכנס ללוג, כל עוד לא נכתבת לקובץ
  • תוכנה שמוגדרת להדפיס למסך (כלומר לא רצה ברקע) - הלוגים שלה יופיעו ב־docker logs, כי היא מדפיסה פלט רגיל
  • כתיבה ל־/proc/1/fd/1 - כתיבה ישירה למסך של התהליך הראשי – נשמרת בלוג

        פרוש של  - /proc/1/fd/1:
  • /proc/ - תקיית מידע פנימית של לינוקס
  • "1" - זה ה- PID של התהליך הראשי בקונטיינר (מה שהרצנו כשייצרנו אותו)
  • fd/1 - קובץ שמייצג את "המסך" (OutPut) של אותו התהליך
  • לכן יש סדר פעולות שצריך לבצע במידה ולא הפעלתם את הקונטיינר עם לוגים

מה לא ירשם בלוגים?

  • docker exec echo "משהו" - לא נכנס ללוגים – זה תהליך צדדי, לא חלק מהתהליך הראשי
  • כתיבה לקובץ בתוך הקונטיינר - לא יופיע בלוגים – כי זה נכתב לקובץ ולא למסך
  • תוכנה שרצה ברקע בלי פלט - אם היא לא מדפיסה למסך – אין מה שייכנס ללוגים

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

1) לעצור את הקונטיינר - docker stop container_name
2) למחוק את הקונטיינר - docker rm continer name
3) להריץ מחדש את הקונטיינר שאנחנו רוצים:

'docker run -d --name test1 alpine sh -c 'echo "LeiderTech.co.il" && tail -f /dev/null

הפרוש של הפקודה:
  • docker run - יוצר ומריץ קונטיינר חדש

  • -d - מריץ את הקונטיינר ברקע (detached) — אתה לא תראה את הפלט במסך

  • --name test1 - נותן לקונטיינר את השם test1

  • alpine - ה Image שמשמשת להרצת הקונטיינר – Alpine היא לינוקס קליל

  • sh -c '...' ה" C" הוא בעצם קיצור של "command", ה "SH" הוא בעצם קיצור של "SHELL" בתוך הקונטיינר

  • echo "LeiderTech.co.il" - מדפיס את הטקסט למסך (Output) — ונשמר בלוג

  • && - (כמו שכבר למדנו בפרקים הקודמים) מפעיל את הפקודה הבאה רק אם הקודמת הצליחה

  • tail -f /dev/null - שומר את הקונטיינר חי בלי לעשות כלום (מונע ממנו להיסגר)

3.איך לשנות שם של קונטיינר בדוקר? - docker rename old_name new_name


נגיד והחלטתם לשנות את השם שלקונטיינר כלשהו, אין צורך בלעצור את הקונטיינר ניתן פשוט לבצע שינוי בצורה הבאה:
docker rename test3 test9
לאחר מכן נריץ את docker ps ונראה שבוצע השינוי:


שימו לב :אין אפשרות לעשות שינוי שם לקונטיינר שנמצא במצב "הקפאה" (Paused).


4.איך להריץ פקודות בתוך קונטיינר שכבר רץ בדוקר? - docker exec


מטבע הדברים נרצה לבצע פעולות בתוך הקונטיינר,  וכל זה נעשה בעזרת פקודות כאלה ואחרות, לא בכל פעם צריך להתחבר לתוך הקונטיינר ולעבוד, ניתן לבצע פעולות מבחוץ ולקבל תגובה, לדוגמא, אם אנחנו רוצים להציג תוכן של תיקייה או לבדוק כתובת IP, לא צריך להתחבר לתוך הקונטיינר, ניתן "לשלוח" פקודה לתוך הקונטיינר ולקבל את הפלט של הפקודה נגיד ואנחנו רוצים לבדוק כתובת IP של קונטיינר מסויים, נריץ את הפקודה הבאה: docker exec command continaner_name

בלינוקס בודקים כתובות IP עם הפקודה "ip a" ומה שיקרה, זה שלאחר שנריץ את הפקודה נקבל את הפלט שלה, אני אבצע בדיקה בקונטיינר בשם test83 בצורה הזאת: docker exec test83 ip a



נגיד ואני רוצה לראות מה יש בתוך תקיית "var" בתוך הקונטיינר "LeiderTech", אני אריץ את הפקודה הבאה: 

docker exec leidertech ls -l /var

ונקבל את התוכן בלי הצורך להתחבר לקונטיינר עצמו:



פרמטרים נוספים:
  • -i - מאפשר לשלוח לקונטיינר קלט מהמשתמש (לדוגמא: טקסט, קובץ)
    להלן כמה דוגמאות שיהיה יותר קל להבין:

    נגיד ואנחנו רוצים לשלוח טקסט לתוך קובץ בקונטיינר:

    echo "hello docker" | docker exec -i test1 tee /tmp/hello.txt > /dev/null

    נגיד ואנחנו רוצים לשלוח סקריפט שלם להרצה בתוך הקונטיינר:
    docker exec -i test1 sh < script.sh

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



  • -it - שילוב של -i ו־-t — מאפשר לעבוד בתוך הקונטיינר עצמו
  • --detach או -d - מריץ את הפקודה ברקע בתוך הקונטיינר - הסבר יש בסעיפים הקודמים
  • --env או -e - מעביר משתנה סביבה לתוך הפקודה
  • --user או -u - מריץ את הפקודה כמשתמש אחר בתוך הקונטיינר - להלן דוגמא:
    docker exec -u root leidertech whoami



  • --privileged - מריץ את הפקודה בהרשאות מלאות (למשל לצורכי ניהול רשת, התקנים וכו׳), בעזרת הדגל הזה, תוכלו לבצע פעולות בין המחשב לקונטיינר עצמו.

  • --workdir או -w - קובע את התיקייה שבה תבוצע הפקודה בתוך הקונטיינר נגיד:
    docker exec -w /tmp leidertech pwd



    (אם אתם לא יודעים מה זה pwd - אתם צריכים לעבור על המדריך לינוקס למתחילים: כאן)

5.איך להעתיק קבצים מהמחשב לקונטיינר וההפך בדוקר? - docker cp


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

5.א נתחיל עם העתקה מהמחשב לקונטיינר.


להלן הסינטקס: docker cp host_path container_name:container_path

יש לי במחשב קובץ בשם test1.txt ואני רוצה להעתיק אותו לאיזשהי תיקייה בתוך הקונטיינר LeiderTech לתיקיית tmp:

/docker cp ~/Desktop/test1.txt leidertech:/tmp




ניתן לראות שההעתקה בוצעה בהצלחה, עכשיו נבדוק שהקובץ באמת שם:


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

5.ב העתקה של קבצים מהקונטיינר למחשב


להלן הסינטקס: docker cp container_name:path_inside_container path_on_host

את הקובץ שהעתקתי בסעיף הקודם בשם test1.txt אני רוצה להעתיק מהקונטיינר LeiderTech לתקיית lev1 במחשב שלי:

docker cp leidertech:/tmp/test1.txt ~/Desktop/lev1



נבדוק שהקובץ נמצא בתיקייה Lev1:



5.ג האם אפשר לבצע העתקה של כמה קבצים\תיקיות בדוקר?

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

5.ד האם אפשר לבצע "גזירה" (CUT) לקבצים\תיקיות בדוקר?


התשובה היא לא - אין אפשרות לבצע פעולה כזאת.


6.עבודה עם Volumes - איך לחבר תיקייה\כונן\אלפקה במחשב שלנו לקונטיינר בדוקר - docker run -v


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

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

יש כמה צורות של עבודה עם תיקיות:
1) חיבור תיקייה במחשב שלנו לתוך הקונטיינר - ובעצם אנחנו עובדים רגיל כמו שאנחנו מכירים - צורת Bind
2) חיבור סוג של "דיסק חיצוני" לקונטיינר - ובעצם מי שמנהל אותו זה הדוקר - צורת Volume
3) חיבור תיקייה מהמחשב שלנו "לקריאה בלבד".

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


אז כפי שאמרנו, אם אנחנו רוצים לחבר כל תיקייה מהמחשב שלנו לתוך הקונטיינר כי יש עליו חומר שהקונטיינר צריך, 
נבצע "bind" (חיבור) של תיקייה במחשב לתוך קונטיינר בשם leidertech.

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

1) נעצור ונמחק את הקונטיינר docker rm -f leidertech



2) נריץ את הפקודה לחיבור התיקייה לתוך הקונטיינר leidertech שניצור מחדש, בסינטקס הישן ואז בחדש:

סינטקס ישן - docker run --name leidertech -v ~/Desktop/sharefolder:/data alpine

(מאחר ואני לא רוצה לעבוד בתוך הקונטיינר, לא השתמשתי ב "it-" מה שקרה, זה שמערכת פשוט יצרה קונטיינר וחיברה לו את התיקייה sharefolder).



סינטקס חדש -  
docker run --name leidertech --mount type=bind,source=$HOME/Desktop/sharefolder,target=/data alpine

(הוא יותר ארוך אבל יש בו גם יותר פרטים כמו type (סוג חיבור) ובעצם מוסבר מי המקור ומי היעד)


חיברנו את sharefolder מהמחשב לתוך תיקיית data ועכשיו נציג אותה ונראה מה יש בה, נריץ את הפקודה:

docker exec -t leidertech ls -l /data



ועכשיו נכנס לתוך sharefolder במחשב עצמו בשביל לראות מה יש שם:



ניתן לראות בבירור שמדובר על תוכן זהה.

בשביל הנסיון, אצור תיקייה בשם lev3 בתוך sharedfolder במחשב, ואז את התיקייה lev3 שיצרתי במחשב, נוכל לראות גם בקונטיינר:



6.ב איך לבצע ניתוק של תיקייה מתוך קונטיינר בדוקר או UnBind?


התשובה מאוד פשוטה - אין אפשרות לבצע את זה, צריך למחוק את הקונטיינר וליצור אחד חדש בלי Bind.


6.ג איך לבצע חיבור Volume לקונטיינר בדוקר?


נתחיל מההסבר הפשוט, מה זה בכלל Volume בדוקר ומה המטרה שלו?, אז בעצם מדובר במצב שבו אתם כאילו מחברים "דיסק חיצוני" לתוך הקונטיינר, מאחורי הקלעים, ברגע שתבצעו את הפקודה המתאימה, דוקר יצור תיקייה ריקה במחשב שלכם (בנתיב הזה /var/lib/docker/volumes/) ויקשר אותה לתיקייה שאתם תגידו לו בתוך הקונטיינר ואז תוכלו לשמור שם דברים, אם מוחקים את הקונטיינר, ה-Volume לא נמחק, וניתן להשתמש בו בקונטיינר אחר, דיי מזכיר עבודה עם דיסק וירטואלי שאפשר להעביר ממחשב למחשב.


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


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

1) נעצור ונמחק את הקונטיינר leidertech עם הפקודה docker rm -f leidertech


2) ניצור קונטיינר חדש עם ה Volume הרצוי, כמו פעם קודמת נראה סינטקס ישן ואז חדש.

סינטקס ישן - docker run -d --name leidertech -v levs:/data alpine tail -f /dev/null



(השתמשתי ב "d-" בשביל שלאחר הפקודה, הקונטיינר פשוט ירוץ ולא יחבר אותי לסשן של הקונטיינר שנוצר)


נבדוק שנוצר ה Volume בעזרת הפקודה docker volume ls:



סינטקס חדש:
docker run -d --name leidertech --mount type=volume,source=levs,target=/data alpine tail -f /dev/null

(כמו פעם קדמת, יותר ארוך, אך עם הרבה יותר פרטים)

1) מחקתי את הקונטיינר הקיים עם docker rm -f leidertech
2) יצרתי את הקונטיינר וחיברתי את ה Volume
3) אני מציג את ה Volume שנוצר עם docker volumes ls




6.ד איך לבצע ניתוק של Volume מקונטיינר?


אין ממש פקודה לבצע את הפעולה הזאת, צריך למחוק את הקונטיינר ולייצר אחד חדש בלי Volume.


6.ה איך לייצר חיבור לתיקייה במצב "קריאה בלבד"?


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

לידע כללי - ניתן לבצע BIND או VOLUME במצב של "קריאה בלבד".

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

1) נעצור ונמחק את הקונטייר הקיים docker rm -f leidertech.



2) ניצור קונטיינר חדש ונחבר לו תיקייה (בעזרת BIND) במצב RO (קיצור של READ ONLY).

סינטקס ישן - docker run -d --name leidertech -v ~/Desktop/sharefolder:/data:ro alpine tail -f /dev/null



סינטקס חדש - docker run -d --name leidertech --mount type=bind,source=$HOME/Desktop/sharefolder,target=/data,readonly alpine tail -f /dev/null

(ארוך אבל יותר ברור)


בשיטה החדשה, הרבה יותר ברור איפה לשנות את מה שאנחנו רוצים, זאת אומרת צריך לשנות את "bind" ל "Volume" וזה ברור מה אנחנו רוצים לחבר, בנוסף במקום "read only" אפשר לרשום "rw" (קיצור של Read\Write) וזה יחבר כבר בצורה של קריאה\כתיבה, בעיקרון אם לא כותבים "ro", בתור ברירת מחדל, החיבור יתבצע במצב "rw".

יש עוד פרמטרים בשימוש עם Bind, שב 99% לא תשתמשו בהם אבל בשביל שתדעו שהם קיימים להלן, חלק מאופציות מתקדמות של Bind-propagation  (הפקודות בשיטה החדשה מאוד מאוד ארוכות, אז תסלחו לי 😅)

rprivate - (ברירת מחדל) — שינויים לא מופצים לשום כיוון

docker run -d --name mycontainer --mount type=bind,source=$HOME/Desktop/sharefolder,target=/data,bind-propagation=rprivate alpine tail -f /dev/null

private - כמו rprivate, אבל לא עובד על תת־mountים

docker run -d --name mycontainer --mount type=bind,source=$HOME/Desktop/sharefolder,target=/data,bind-propagation=private alpine tail -f /dev/null

rshared - שינויים מופצים לשני הצדדים
docker run -d --name mycontainer --mount type=bind,source=$HOME/Desktop/sharefolder,target=/data,bind-propagation=rshared alpine tail -f /dev/null

shared - שינויים מהקונטיינר מופצים החוצה
docker run -d --name mycontainer --mount type=bind,source=$HOME/Desktop/sharefolder,target=/data,bind-propagation=shared alpine tail -f /dev/null

slave - רק שינויים מהמחשב עוברים לקונטיינר
docker run -d --name mycontainer --mount type=bind,source=$HOME/Desktop/sharefolder,target=/data,bind-propagation=slave alpine tail -f /dev/null

rslave - כמו slave, אבל גם עם תת־mountים
docker run -d --name mycontainer --mount type=bind,source=$HOME/Desktop/sharefolder,target=/data,bind-propagation=rslave alpine tail -f /dev/null

7. להציג Volumes  בדוקר? - docker volume ls


אם אני רוצה להציג את כל ה VOLUMES שיש לי בדוקר (זאת אומרת את כל מה שחיברתי בכל קונטיינר), אשתמש בפקודה docker volume ls


להלן כל הפרמטרים עם דוגמאות:

  • -f או --filter - סינון לפי קריטריונים (כמו שם, דרייבר)
    docker volume ls -f name=levs

    docker volume ls -f driver=local

    נגיד אני רוצה להבין לאן מחובר lev_mount_2:
    docker ps -a --filter volume=lev_mount_2
    נקבל תשובה בהתאם:


  • --format - עיצוב מותאם אישית לפלט (Go Templates)
    הצגת שם ודרייבר:
    "docker volume ls --format "{{.Name}} - {{.Driver}}
    הצגת רק שמות:
    '""docker volume ls --format '"{{.Name}}

  • -q או --quiet - מציג רק את שמות ה־Volumes בלי מידע נוסף (טוב לשימוש בסקריפטים)
    docker volume ls -q



8.איך למחוק Volume  בדוקר? - docker volume rm


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

¿?חשוב לזכור - אין אפשרות למחוק VOLUME כשהקונטיינר רץ, לכן קודם צריך למחוק אותו

ורק לאחר מכן תוכלו למחוק את ה VOLUME¿?

בשביל למחוק VOLUME, נריץ את הפקודה docker volume rm volume_name.

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

1) לעצור ולמחוק את הקונטיינר עם הפקודה docker rm -f contianer_name 


2) לאחר מכן נמחק את ה VOLUME הרלוונטי:


3) נבדוק שה VOLUME לא מופיע יותר:


8.א האם אפשר למחוק כמה VOLUME ביחד בפעם אחת?

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

docker volume rm vol1 vol2

8.ב איך למחוק הרבה VOLUME ביחד שלא צריך?


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

1) פקודה שתשאל "האם אתם בטוחים?" - docker volume prune

2) פקודה "שגר ושכח" - docker volume prune -f

שימו לב - לאחר מחיקת VOLUME אין שום אפשרות לשחזר !!

9. איך עושים "סדר פסח" בדוקר ומנקים Imageים שלא בשימוש כבר בדוקר - docker image prune

אז כמו בסעיף הקודם, אותו דבר יש עם IMAGEים, ניתן למחוק את כולם עם הפקודה prune.

לידע כללי - ב IMAGEים יש הבדל בין IMAGE רגיל לבין IMAGE שהוא "dangling", אימג' שהוא dangling נוצר במידה ויצרו אימג' חדש על אימג' ישן (דרסו אותו), אימג' שיצרו בלי TAG (זאת אומרת בלי לתת לו שם), או אם בונים אימג' ועצרנו באמצע את התהליך (אנחנו נלמד בחלק 5 על Docker build).

לצורך דוגמא, יש לי IMAGE אחד כזה שהוא Dangling, ניתן לראות אותו ברשימה כאן,
הוא מופיע ללא TAG וללא Repository, נריץ את docker images בשביל להציג את כל ה IMAGEים שיש לי:



כמו למחיקה של VOLUME, גם כאן יש שתי פקודות, אחת שואלת האם למחוק והשניה היא "שגר ושכח":

1) פקודה בטוחה יותר ששואלת שאלה - docker image prune
להלן דוגמא, המערכת שואלת האם אנחנו בטוחים:

לחצתי על "y" וקיבלתי הודעה שה IMAGE נמחק:


2) פקודה "שגר ושכח" - docker image prune - f
להלן דוגמא עם הפקודה שהיא "שגר ושכח" והאימג' פשוט נמחק:

יש עוד שתי פקודות, שמוחקות את כלל האימג'ים באותו סגנון, אחת שואלת "האם אתה בטוח בלה בלה בלה?" והשניה היא "שגר ושכח":
1) פקודה בטוחה - docker image prune -a:

והמערכת מחקה לי המון אימג'ים והחזירה לי 279 מגה:

2) עכשיו ננסה את הפקודה שהיא שגר ושכח - docker image prune -a -f:
בלי שאלות, בלי שום דבר, ישר מחק:



9.איך לבדוק כמה משאבים צורך כל קונטיינר בדוקר - docker stats

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

בשביל לצאת מהמצב הזה נלחץ על CTRL+C.

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

  • --no-stream - מציג את הנתונים פעם אחת בלבד, בלי המשכיות: docker stats --no-stream




  • --format - מאפשר להציג את הנתונים בפורמט מותאם אישית עם תבניות:

    "docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}} - בצורה הזאת המידע שוב
    ירוץ בזמן אמת ו"יתקע" לכם בסשן, לכן צריך לשלב את זה עם הפרמטר מהסעיף הקודם:

    docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

  • --no-trunc - מציג את המידע המלא בלי לקצר ערכים כמו מזהי קונטיינרים:



11. תקשורת בדוקר – איך לחבר בין קונטיינרים ולפתוח פורטים?

לפני שנמשיך חשוב להכיר כמה פרמטרים רלוונטיים לפקודה docker network ומתאימה לכלל סוגי הרשתות:
  • docker network ls - הצגת כל הרשתות הקיימות
  • <docker network inspect <network_name - הצגת מידע מפורט על רשת
  • <docker network create <network_name - יצירת רשת חדשה (ברירת מחדל היא Bridge)
  • <docker network rm <network_name - מחיקת רשת קיימת
  • docker network prune - מחיקת כל הרשתות שאינן בשימוש
חשוב לשים לב שאין אפשרות לפתוח פורטים לקונטיינר קיים, יש צורך ביצירת קונטיינר חדש עבור הפעולה הזאת.

כמו בכל סביבה וירטואלית גם כאן יש כמה סוגי רשתות, 4 עיקריות שמוגדרות מראש ואחת שהמשתמש יכול להגדיר לבד:

1. רשת מסוג "Bridge" (ברירת מחדל):
   - הרשת הסטנדרטית של דוקר.
   - כל קונטיינר מקבל IP פנימי משלו.
   - מאפשרת תקשורת בין קונטיינרים.

2. רשת מסוג "Host":
   - הקונטיינר משתמש ישירות ברשת של המחשב המארח.
   - אין בידוד רשת בין הקונטיינר למארח.

3. רשת מסוג "None" - קונטיינר ריק ללא חיבור לרשת בכלל:
   - הקונטיינר ללא חיבור רשת בכלל.
   - מבודד לגמרי מבחינה רשתית.

4. רשת מסוג "User-defined" - רשת שהיא "מותאמת אישית":
   - רשת שנוצרת ידנית לפי דרישות המשתמש.
   - מאפשרת שליטה ובידוד מוגברים בתקשורת בין קונטיינרים.

אלו הן ארבעת סוגי הרשתות העיקריים בדוקר.

לידע כללי יש גם: Overlay, Macvlan ,IPVlan -ניתן לקרוא עליהן ברשת - הן פשוט פחות נפוצות.

11.א - רשת מסוג "Bridge"


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

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

11.א.א. איך יוצרים רשת מסוג Bridge בדוקר?


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

כיצד ליצור רשת מותאמת אישית, אני אסביר בסעיף שמדבר על רשתות מותאמות אישית :)


11.א.ב. איך פותחים פורטים לקונטיינר בדוקר - שילבתי כאן גם את BRIDGE וגם את נושא פתיחת הפורטים.


מאחר ויש שירותים שמצריכים פתיחת פורטים, יש צורך בביצוע הפעולה על מנת שנוכל לגשת לשירות כזה או אחר מבחוץ, לצורך כך נשתמש בפרמטר מאוד חשוב p-, הסינטקס הוא כזה:
 docker run -d -p [your_computer_port]:[container_port]  --name ubuntu sleep infinity

( במקרה הזה sleep infinity מורה לקונטיינר להפסיק כל פעילות אחרת ולהישאר פעיל למשך זמן בלתי מוגבל.)

לצורך הדגמה, ניצור קונטיינר קטן עם שרת דואר ונפתח את פורט 80 בקונטיינר, ואצלינו במחשב נחבר אותו ל 8080:
docker run -d --name leidertechs_ports_test -p 8080:80 nginx



ועכשיו אחרי שפתחנו פורט עם p-, מה שקורה הוא שהפורט שבקונטיינר מחובר לפורט במחשב שעליו רץ Docker.

לכן – אם אנחנו רוצים לגשת לשירות (במקרה הזה שרת nginx) שבקונטיינר ממחשב אחר ברשת, אנחנו לא ניגשים לקונטיינר, אלא לכתובת ה־IP של המחשב שמריץ את הסביבה של הדוקר.

נבצע בדיקה של הכתובת: 

לאחר מכן, מאחר והרצנו NGINX (שהוא שרת WEB, יש לו עמוד של "ברוכים הבאים) ואנחנו נוכל לראות אותו:



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

כמו כן, במידה ונריץ עכשיו docker ps, נוכל לראות את הפורט שפתחנו:


פרמטרים נוספים שהם יחודים אך ורק לרשת Bridge:
  • --driver bridge - יוצר רשת מסוג - דוגמא:
    bridge | docker network create --driver bridge my-bridge

  • --subnet - קובע את טווח כתובות ה IP דוגמא:
     docker network create --subnet 192.168.100.0/24 my-subnet-net

  • --gateway  -  מגדיר כתובת gateway דוגמא:
     docker network create --subnet 192.168.100.0/24 --gateway 192.168.100.1 my-gateway-net

  • --ip-range - תחום IP לקונטיינרים בתוך הרשת דוגמא:
    docker network create --subnet 192.168.100.0/24 --ip-range 192.168.100.128/25 my-range-net

  • -o com.docker.network.bridge.name=br0 -  (אופציונלי) שם רשת פנימי בלינוקס דוגמא:
     docker network create -o com.docker.network.bridge.name=br0 my-custom-bridge

11.א.ג רשת מסוג "Host"

למה שנרצה לחבר קונטיינר כזה? בעיקרון נגיד ויש לנו שרת אינטרנט ואנחנו לא רוצים להתחיל להתעסק עם פורטים כי אנחנו יודעים ישר שהשירות\אפליקציה הולכים לעבוד באינטרנט ואנחנו נצטרך לגשת אליו, כאן אין פרמטר p- ואנחנו נראה את זה עכשיו בהדגמה, אני אמחק את הקונטיינר האחרון שיצרתי ואצור אחד חדש בלי הפניית פורט וזה יעבוד, במקרה הזה אני כן אציין שאני רוצה לפתוח רשת מסוג Host:

docker run -d --name leidertech_host_network_test --network host nginx


וזה עובד בלי בעיה:

11.א.ד רשת מסוג "None":

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

לצורך דוגמא ניצור קונטיינר כזה ללא חיבור לרשת:
docker run -d --network none --name leidertech-no-net-container ubuntu sleep infinity



ועכשיו אתחבר לתוך הקונטיינר עם הפקודה: docker exec -it no_network_container bash,

ואנסה לבצע בתוכו את apt update:

וניתן לראות שלא מצליחים לעשות כלום כי אין תקשורת:



11.א.ה.רשת מסוג "User-defined"

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

  • --driver - מגדיר את סוג הרשת (לרוב bridge) - --driver bridge לדוגמא:
    docker network create --driver bridge my-net

  • --subnet - קובע את טווח כתובות ה־IP ברשת - --subnet 172.16.0.0/16 לדוגמא:
    docker network create --subnet 172.16.0.0/16 my-subnet-net

  • --gateway - מגדיר את כתובת השער ברירת מחדל(gateway) ברשת - --gateway 172.16.0.1 לדוגמא:
    docker network create --subnet 172.16.0.0/16 --gateway 172.16.0.1 my-gateway-net

  • --ip-range - תחום כתובות IP שיחולקו לקונטיינרים על ידי המערכת (דוקר)- --ip-range 172.16.1.0/24 לדוגמא:
    docker network create --subnet 172.16.0.0/16 --ip-range 172.16.1.0/24 my-range-net

  • --ipv6 - מפעיל תמיכה ב־IPv6 ברשת - --ipv6 לדוגמא:
    docker network create --ipv6 --subnet 172.16.0.0/16 my-ipv6-net

  • --label - מוסיף תגית (metadata) לזיהוי הרשת - --label env=dev לדוגמא:
    docker network create --label env=dev my-labeled-net
נריץ פקודה לדוגמא שתייצר לנו רשת בשם leider_net:

docker network create --driver bridge --subnet 172.16.0.0/24 --gateway 172.16.0.1 --ip-range 172.16.0.128/28 leider_net


עכשיו נריץ את docker network ls בשביל לבדוק את כל השרתות שיש לנו ונוכל לראות שם את הרשת שיצרנו:


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

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

הינה רשימת הקונטיינרים שיש לי :

אנחנו נקח את Leidertech1 ואת leidertech2 ונחבר אותם ל leider_net (מקורי לא? 😅), אז קודם כל צריך לעצור את הקונטיינרים בעזרת הפקודה: docker stop leidertech1 leidertech2



השלב הבא יהיה לחבר אותם לרשת החדשה leider_net, רק שבמקרה הזה, אין אפשרות לשרשר כמה קונטיינרים ביחד, ניתן לחבר כל פעם רק קונטיינר אחד (לא יודע למה לא איפשרו את זה עדיין, זה די מעיק האמת), אבל אפשר לשרשר את הפקודה בעזרת סימן ";" בין הפקודות בצורה הזאת:
docker network connect leider_net leidertech1; docker network connect leider_net leidertech2

ומאחר ולא קיבלנו שום הודעת שגיאה, זה אומר שזה עבד:


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

docker inspect -f '{{range $k, $v := .NetworkSettings.Networks}}{{println $k}}{{end}}' leidertech1

?¿לידע כללי?¿:
אם יצא לכם לכתוב סקריפטים או לתכנת, אז בעצם Range היא לולאת "For" מתוך שפת Go Lang.

בפלט ונוכל לראות את סוג הרשת והשם של הרשת שאליה מחובר הקונטיינר:


במצב אחר, עם docker inspect leidertech2 |less נוכל לראות את הרשת בצורה אחרת (כפי שלמדנו בסעיף הראשון)




וכמו תמיד אני מצרף לכם את כל הפרטמרים הקיימים שקשורים ברשת מותאמת אישית:
  • --driver
  • --subnet
  • --gateway
  • --ip-range
  • --ipv6
  • --attachable
  • --internal
  • --label
  • -o com.docker.network.bridge.name
  • -o com.docker.network.bridge.enable_icc
  • -o com.docker.network.bridge.enable_ip_masquerade
  • -o com.docker.network.driver.mtu

זה הכל להפעם

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

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

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

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

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


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