אהלן לכם, וברוכים הבאים לחלק השלישי במדריך "דוקר למתחילים בעברית"!
בפרק הזה נצלול קצת יותר לעבודה אמיתית עם קונטיינרים שכבר רצים – נלמד איך לבדוק עליהם מידע, להסתכל על הלוגים שלהם, לשנות להם שם, להעביר קבצים פנימה והחוצה, ולהריץ בתוכם פקודות.
נמשיך גם לדברים סופר חשובים כמו חיבור תיקיות מהמחשב שלנו עם 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
מידע על קונטיינר מסוים זה מאוד חשוב, לפעמים אנחנו רוצים לדעת מה הנפח שלו, או לדוגמא אם אתם לא זוכרים מה הפקודה שהוא מריץ?
לידע כללי, מה זה 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 -f '{{.State.Status}}' test1
- docker inspect --format '{{.State.Status}}' test1
1.א. איך להציג שדה ספציפי עם docker inspect?
איך בעצם נדע כיצד לגשת ל Status?
לכל "סעיף" בקובץ יש "כותרת" שהיא נמצאת בתוך "" ולאחר מכן יש סימן של נקודתיים ":", לאחר מכן סוגר מסולסל "{" ובפנים יש כל מיני תתי סעיפים, והראשון שמופיע הוא: "State"
נגיד ואני רוצה לגשת ל Pid, אני אכתוב: docker inspect --format '{{.State.Pid}}' test1:
2. איך לבדוק לוגים בקונטיינר של דוקר? - docker logs
לוגים זה דבר מאוד מאוד חשוב, בחלק הזה אנחנו נלמד כיצד לקרוא לוגים, לשמור אותם בצד ואפילו לשמור אותם בלייב.
חשוב להבהיר משהו אחד: אנחנו לא מדברים כאן על לוגים של מערכת ההפעלה — כמו ה־Events שאתם אולי מכירים מ־Windows.
מה ש־docker logs מציג זה לא שגיאות מערכת, אלא יותר כמו רישום של פלט שהאפליקציה בתוך הקונטיינר הדפיסה,
זה יכול להיות טקסט שהצגנו למשתמש, שגיאות שהופיעו כשהאפליקציה קרסה, הודעות echo, print, או לוגים שהאפליקציה בחרה להציג החוצה למסך.
אם בדרך כלל אנחנו מבצעים פקודה ושמים בסוף את השם של הקונטיינר, במקרה הזה ניתן לשים גם את ה id של הקונטיינר, נתחיל בלהבין איפה אנחנו בכלל מוצאים את ה ID של הקונטיינר או השם שלו?, אז ניתן למצוא את השם וה ID בעזרת הפקודה docker ps או docker ps -a (אם אתם לא יודעים מה זה או מה ההבדל, תעברו על החלק הראשון דחוף : כאן).
לראות לוגים במקרה הזה לא כל כך פשוט וצריך לשים לב שבשביל באמת לקבל לוגים אנחנו נצטרך להריץ את הקונטיינר מההתחלה בצורה כזאת שהוא ישמור לוגים, אחרת הוא לא ישמור אותם ולא תראו כלום.במידה ואתם יוצרים עכשיו קונטיינר חדש ואתם רוצים שהוא ירשום הכל ללוג, הינה פקודה לדוגמא:
- 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" - זה ה- PID של התהליך הראשי בקונטיינר (מה שהרצנו כשייצרנו אותו)
- fd/1 - קובץ שמייצג את "המסך" (OutPut) של אותו התהליך
- לכן יש סדר פעולות שצריך לבצע במידה ולא הפעלתם את הקונטיינר עם לוגים
מה לא ירשם בלוגים?
- docker exec echo "משהו" - לא נכנס ללוגים – זה תהליך צדדי, לא חלק מהתהליך הראשי
- כתיבה לקובץ בתוך הקונטיינר - לא יופיע בלוגים – כי זה נכתב לקובץ ולא למסך
- תוכנה שרצה ברקע בלי פלט - אם היא לא מדפיסה למסך – אין מה שייכנס ללוגים
- 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
4.איך להריץ פקודות בתוך קונטיינר שכבר רץ בדוקר? - docker exec
- -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
5.א נתחיל עם העתקה מהמחשב לקונטיינר.
להלן הסינטקס: docker cp host_path container_name:container_path
5.ב העתקה של קבצים מהקונטיינר למחשב
5.ג האם אפשר לבצע העתקה של כמה קבצים\תיקיות בדוקר?
5.ד האם אפשר לבצע "גזירה" (CUT) לקבצים\תיקיות בדוקר?
6.עבודה עם Volumes - איך לחבר תיקייה\כונן\אלפקה במחשב שלנו לקונטיינר בדוקר - docker run -v
1) חיבור תיקייה במחשב שלנו לתוך הקונטיינר - ובעצם אנחנו עובדים רגיל כמו שאנחנו מכירים - צורת Bind
6.א איך לבצע BIND לקונטיינר בדוקר?
6.ג איך לבצע חיבור Volume לקונטיינר בדוקר?
6.ד איך לבצע ניתוק של Volume מקונטיינר?
6.ה איך לייצר חיבור לתיקייה במצב "קריאה בלבד"?
בשיטה החדשה, הרבה יותר ברור איפה לשנות את מה שאנחנו רוצים, זאת אומרת צריך לשנות את "bind" ל "Volume" וזה ברור מה אנחנו רוצים לחבר, בנוסף במקום "read only" אפשר לרשום "rw" (קיצור של Read\Write) וזה יחבר כבר בצורה של קריאה\כתיבה, בעיקרון אם לא כותבים "ro", בתור ברירת מחדל, החיבור יתבצע במצב "rw".
7. להציג Volumes בדוקר? - docker volume ls
- -f או --filter - סינון לפי קריטריונים (כמו שם, דרייבר)docker volume ls -f name=levs
- --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ים שיש לי:
להלן דוגמא, המערכת שואלת האם אנחנו בטוחים:
לחצתי על "y" וקיבלתי הודעה שה IMAGE נמחק:
להלן דוגמא עם הפקודה שהיא "שגר ושכח" והאימג' פשוט נמחק:
יש עוד שתי פקודות, שמוחקות את כלל האימג'ים באותו סגנון, אחת שואלת "האם אתה בטוח בלה בלה בלה?" והשניה היא "שגר ושכח":
והמערכת מחקה לי המון אימג'ים והחזירה לי 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 ls - הצגת כל הרשתות הקיימות
- <docker network inspect <network_name - הצגת מידע מפורט על רשת
- <docker network create <network_name - יצירת רשת חדשה (ברירת מחדל היא Bridge)
- <docker network rm <network_name - מחיקת רשת קיימת
- docker network prune - מחיקת כל הרשתות שאינן בשימוש
לידע כללי יש גם: Overlay, Macvlan ,IPVlan -ניתן לקרוא עליהן ברשת - הן פשוט פחות נפוצות.
11.א - רשת מסוג "Bridge"
את סוג הרשת הזאת, דוקר יוצר בתור ברירת מחדל כשלא אומרים לו משהו אחר, ברת הזאת הקונטיינרים מתקשרים ביניהם במידה וצריך, כל קונטיינר מקבל כתובת IP פנימית משלו ויש לו אפשרות לגשת לכל קונטיינר אחר לפי שם או לפי IP.
11.א.א. איך יוצרים רשת מסוג Bridge בדוקר?
בתור ברירת מחדל, רק אם נרצה ליצור רשת מותאמת אישית (עם שם שאנחנו נרצה וכד') נצטרך לציין שאנחנו רוצים ליצור רשת מסוג Bridge, במצב אחר, מספיק להריץ פקודה רגילה להרצת\יצירת קונטיינר והרשת שתיווצר היא Bridge.
11.א.ב. איך פותחים פורטים לקונטיינר בדוקר - שילבתי כאן גם את BRIDGE וגם את נושא פתיחת הפורטים.
לאחר מכן, מאחר והרצנו NGINX (שהוא שרת WEB, יש לו עמוד של "ברוכים הבאים) ואנחנו נוכל לראות אותו:
וכפי שניתן לראות הכל עובד, סימן שפתחנו פורטים נכון.
- --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
למה בעצם צריך רשת מסוג "None"? , המטרה של חיבור רשת כזה, הוא מאוד פשוט, נגיד ואתם רוצים לבצע בדיקות של תוכנה בלי "הפרעות" מהרשת, או להשתמש במחשב שהוא עם אפליקציה אחת שלא צריכה לגשת לרשת, יש המון תסריטים לנושא הזה, קונטיינר שהמטרה שלו להיות "מכונה" או משהו כזה שלא מצריך רשת.
ואנסה לבצע בתוכו את apt update:
- --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
עכשיו אחרי שיצרנו רשת, צריך לחבר אליה מחשבים, או במקרה שלנו קונטיינרים ולבדוק ביניהם תקשורת.
אנחנו נקח את 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, שזאת סביבת שורת הפקודה של לינוקס, זה נושא אחר לגמרי):
אם יצא לכם לכתוב סקריפטים או לתכנת, אז בעצם Range היא לולאת "For" מתוך שפת Go Lang.
וכמו תמיד אני מצרף לכם את כל הפרטמרים הקיימים שקשורים ברשת מותאמת אישית:
- --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
מחכים מאד. תודה רבה
השבמחקתודה רבה על התגובה !
מחקהוספתי את היוטיוב :)