טיפ דוקר: איך להוסיף קוד איתחול לאימג'

05/09/2021

פוסט זה כולל טיפ קצר על Docker. אם אתם רוצים ללמוד יותר לעומק על פיתוח עם Docker, Docker Compose או Kubernetes תשמחו לשמוע שבניתי קורס וידאו מקיף בנושא זה.
למידע נוסף והצטרפות לקורס בקרו בדף קורס Docker כאן באתר.
 

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

1. יצירת אימג' שלנו שמתבסס על אימג' קיים

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

בגיטהאב אני מוצא את תיקיית המקור של האימג'. של מונגו נמצאת כאן: https://github.com/docker-library/mongo

מזהה את ה Dockerfile שלה ומוצא בתוכו את השורות שמגדירות Entrypoint ו CMD. במונגו אלה השורות:

COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 27017
CMD ["mongod"]

זה אומר שנקודת הכניסה של הקונטיינר היא הקובץ /usr/local/bin/docker-entrypoint.sh עם הפרמטר mongod.

נפתח תיקיה חדשה וניצור בתוכה Dockerfile עם התוכן הבא:

FROM mongo:5

COPY docker-entrypoint.sh /my/docker-entrypoint.sh
RUN chmod +x /my/docker-entrypoint.sh

ENTRYPOINT ["/my/docker-entrypoint.sh"]
CMD ["mongod"]

דרסתי את ה Entrypoint עם סקריפט שלי - שכל מה שהסקריפט שלי יעשה הוא להפעיל את ה entrypoint המקורי של מונגו. אני מעביר את mongod ל CMD בדיוק כמו שעשו באימג' המקורי, ומחרוזת זו תעבור בתור פרמטר לסקריפט שלי וממנו לנקודת הכניסה המקורית.

הסקריפט docker-entrypoint.sh שלי אגב הוא ממש פשוט:

#!/usr/bin/env bash

/usr/local/bin/docker-entrypoint.sh "$@"

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

2. הרצת קוד לפני שהדבר שרצינו להפעיל עולה

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

#!/usr/bin/env bash

echo "This code runs before mongo"

/usr/local/bin/docker-entrypoint.sh "$@"

3. הרצת קוד אחרי שהדבר שרצינו להפעיל עולה

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

מילת הקסם כדי להפעיל פקודת bash ברקע היא & ומילת הקסם שעוצרת את הסקריפט עד שתהליכי הרקע מסתיימים היא wait. בשביל להפעיל את ההדפסה אחרי שמונגו עלה אני אוסיף לקונטיינר את wait-for-it ואשתמש בו כדי לחכות שמונגו יעלה.

סך הכל נעדכן את ה Dockerfile לתוכן הבא:

FROM mongo:5

COPY docker-entrypoint.sh /my/docker-entrypoint.sh
RUN apt-get update && \
    apt-get install -y wait-for-it && \
    chmod +x /my/docker-entrypoint.sh

ENTRYPOINT ["/my/docker-entrypoint.sh"]
CMD ["mongod"]

ואת docker-entrypoint.sh לתוכן הבא:

#!/usr/bin/env bash

(/usr/local/bin/docker-entrypoint.sh "$@") &

wait-for-it localhost:27017

echo "This code runs after mongo is ready"

wait

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

  1. מזהים את ה Entrypoint וה CMD של האימג', רושמים אותם בצד. וגם את הפורט מ EXPOSE.

  2. יוצרים אימג' שלנו שיש לו סקריפט entrypoint שמפעיל את ה entrypoint המקורי. לוקחים גם את ה CMD המקורי ואם רוצים להיות נחמדים גם את ה EXPOSE.

  3. אם רוצים להריץ קוד לפני האימג' המקורי אפשר פשוט להוסיף את הקוד ב entrypoint החדש שיצרנו.

  4. אם רוצים להריץ קוד אחרי האימג' המקורי נוסיף את wait-for-it ל Dockerfile, נריץ את האימג' המקורי ברקע, נשתמש ב wait-for-it כדי לחכות שהוא יהיה מוכן ואז נריץ את הקוד שלנו. בסוף נקרא ל wait כדי שהסקריפט entrypoint החדש שכתבנו לא יסתיים והקונטיינר ימשיך לעבוד.