במאמר הראשון של docker הסברתי בצורה כללית על docker. היום אני רוצה לדבר על נושא ספציפי -storage עם דגש על docker persistent storage. איך אפשר להעביר ל-container מידע מה-host? מה הדרכים האפשריות? מה אם ה-container יתרסט? נדבר על כל הדברים האלו היום.
למה שנרצה לשתף מידע עם container?
בסוף, נרצה שהמערכות שלנו ירוצו בתוך container-ים. נגיד שיש לנו container ששומר בתוכו סיסמאות של לקוחות בתוך db כלשהו. מה יקרה למידע אם ה-container יתרסט? הרבה פעמים נשמור מידע חשוב ולא נרצה לאבד אותו. אפילו נרצה להיות מסוגלים לגשת אליו כל הזמן מבלי להיכנס לתוך ה-container. ישנם שלושה פתרונות למצב כזה.
docker persistent storage types
- Bind mounts
- Volumes
docker nonpersistent storage types
- Tmpfs mounts.
לכל אחד מהם יתרונות וחסרונות ועל כן, כל אחד שימושי יותר במקרים מסוימים.
Docker storage – Bind mounts
הכוונה היא לייחוס נתיב כלשהו על ה-host, לתוך ה-container. לדוגמא, אפשר להגדיר שכל מה שנמצא על ה-host בנתיב /etc/data יהיה בתוך ה-container בנתיב /etc/my_dir/data. שני הנתיבים הללו יהיו מסונכרנים ככה שברגע שיהיו שינויים – הם יתעדכנו.
דוגמא:
docker run -d –it --name cool-container-with-bind-mount -v /tmp:/etc/data some-docker-image
הרצנו container והגדרנו לו שימפה בין tmp/ על ה-host ל-etc/tmp/ בתוך ה-container.
בתיעוד הרשמי של docker, הם ממליצים להגדיר את ה-bind mount עם mount– ולא v-.
כדאי להקשיב להם למרות שזה טיפה ארוך יותר. אותה דוגמא תיראה כך עם mount–:
docker run -d -it --name cool-container-with-bind-mount --mount type=bind,source=/tmp,target=/etc/data some-docker-image
אגב, אם אתם רוצים שהתיקייה בה אתם נמצאים תמופה לתוך ה-container, רשמו בערך של ה-source:
- (pwd)$ עבור Linux
- %cd% עבור Windows
היתרון העיקרי של bind mount הוא שזה קל להבנה וקל לשימוש. החיסרון העיקרי הוא שהנתיב על ה-host אינו מנוהל על ידי docker ולכן הוא יכול להימחק/להיהרס יותר בקלות.
Docker storage – volumes
דרך מומלצת יותר לשיתוף קבצים ותיקיות בין ה-host ל-container. ניתן למפות את הנתיב בשתי דרכים.
הדרך הראשונה היא ליצור volume שיווצר תחת התיקייה ש-docker מותקן בה (/var/lib/docker ב-Linux):
docker volume create my-volume
אם מעניין אתכם לדעת מה הנתיב המלא של ה-volume שיצרנו, רשמו:
docker volume inspect my-volume
אחרי שיצרנו את ה-volume אפשר להריץ container איתו:
docker run -d -it --name cool-container-with-volume --mount source=my-volume,target=/etc/data some-docker-image
הדרך השנייה היא להריץ רק את הפקודה האחרונה ואז docker ייצור בשבילנו volume ריק תחת תיקיית ההתקנה שלו.
למה volume עדיף על bind mount?
docker volumes מנוהלים על ידי docker. כלומר, אין תלות ב-host. חשבו איזה בעיות bind mount יכול ליצור אם המיפוי של volume-ים זהה בכל מערכות ההפעלה. הנתיב tmp/ הוא לא נתיב קיים ב-windows ודברים כאלו יכולים להוביל להתנהגויות לא צפויות. כשמשתמשים ב-volume, יש את docker שיידע לבד איפה לשים את הנתיב על ה-host.
משהו נוסף, כיוון שהנתיבים ב-volume יושבים תחת docker יש פחות סכנה שהם ייהרסו (במיוחד כשאנשים מתחברים ומשנים דברים בשרת. בני אדם עושים טעויות לפעמים והם יכולים לשכוח שזה נתיב שמכיל דברים שממופים לתוך container-ים). כשהנתיב יושב תחת /var/lib/docker/ או משהו בסגנון קצת יותר קשה לטעות ?.
Docker storage – Tmpfs mounts
לפי שמם אפשר להבין שהמידע ששמור בהם הוא זמני וייעלם בנסיבות מסוימות. כל מה שנרשום לנתיב כזה יישמר על הזיכרון של ה-host (שהוא נדיף) ולא על הדיסק. כלומר, אם מיפינו נתיב מה-host לתוך ה-container ולאחר מכן יצרנו קובץ בתוך ה-container בנתיב שהוא ממופה אליו – אחרי ריסוט של ה-container הקובץ ייעלם.
כך ניצור את זה:
docker run -d -it --name cool-container-with-tmpfs-mount --mount type=tmpfs,destination=/etc/data some-docker-image
שימו לב שאין source, מהסיבה שזה נשמר על הזיכרון של ה-host. לכן, יש להגדיר רק את הנתיב על ה-container כדי שהמידע תחתיו יישמר בזיכרון.
למה שנרצה להשתמש בדבר כזה?
ישנם מקרים מסוימים בהם נדרש לשמור מידע בצורה לא persistent. כלומר, נרצה שהמידע ייעלם. לדוגמא, כשרוצים לאחסן סיסמא ב-session מסוים אבל רוצים שהסיסמא תימחק לאחר שה-session ייגמר. הקונספט הזה לא זמין במערכות ההפעלה שהן לא Linux כרגע, אבל כן זמין בשאר מערכות ההפעלה.
לסיכום, דיברנו על שלוש דרכים עבור שיתוף מידע בין ה-host ל-container וההפך. אפשר להשתמש בשתי הדרכים השונות עבור persistent storage עם docker, נשתמש בדרך השלישית כשנרצה לשמור מידע באופן זמני.