מה זה Docker Compose¶
ברגע שהבנתם מה זה Docker וידעתם להריץ קונטיינר בודד, מגיע הרגע שבו אתם צריכים יותר מקונטיינר אחד. אפליקציה אמיתית כמעט אף פעם לא רצה לבד - יש לה backend, יש מסד נתונים, יש לרוב Redis או משהו דומה ל-cache, ואולי גם frontend נפרד. וכאן מתחילה הבעיה ש-Docker Compose נועד לפתור.
הבעיה - כשאפליקציה היא בעצם כמה קונטיינרים¶
תיאורטית אפשר להריץ כל שירות עם פקודת docker run נפרדת - אחת ל-backend, אחת למסד הנתונים, אחת ל-Redis. אבל בפועל זה נהיה מסובך מהר מאוד. צריך לזכור את כל הפרמטרים של כל פקודה, לוודא שכל הקונטיינרים יושבים על אותה רשת כדי שיוכלו לדבר אחד עם השני, לנהל volumes כדי שהנתונים לא יימחקו בכל הפעלה מחדש, ולוודא שהסדר נכון - שמסד הנתונים עולה לפני שה-backend מנסה להתחבר אליו.
זה עובד פעם אחת, אבל בפעם השנייה שצריך להרים את הסביבה - אחרי שהמחשב הופעל מחדש, או אצל מפתח חדש בצוות - זה נהיה מקור לשגיאות ולזמן מבוזבז. בדיוק בשביל זה נבנה Docker Compose.
איך docker-compose.yml מתאר את כל הסטאק¶
הרעיון של Compose הוא לתאר את כל הסטאק - כל השירותים, הרשתות וה-volumes - בקובץ YAML אחד שנקרא docker-compose.yml. במקום כמה פקודות נפרדות, יש קובץ אחד שמגדיר, לדוגמה, שירות בשם backend שנבנה מ-Dockerfile מסוים, שירות בשם db שמריץ אימג' של PostgreSQL עם משתני סביבה מסוימים, ושירות בשם cache שמריץ Redis.
בתוך אותו קובץ אפשר גם להגדיר תלויות בין שירותים, אילו פורטים חשופים החוצה, אילו volumes משמשים לשמירת נתונים בין הפעלות, ועל אילו רשתות פנימיות השירותים מדברים אחד עם השני. וזה החלק היפה - Compose יוצר אוטומטית רשת משותפת, כך שכל השירותים יכולים לגשת אחד לשני פשוט לפי שם השירות, בלי להתעסק עם כתובות IP.
docker compose up - זרימת העבודה בפועל¶
ברגע שהקובץ מוכן, כל מה שצריך זה פקודה אחת - docker compose up. Compose קורא את הקובץ, בונה את האימג'ים שצריך לבנות, מרים את כל השירותים בסדר הנכון, ומחבר אותם לאותה רשת. כשמסיימים לעבוד, docker compose down מוריד הכל בחזרה, כולל הרשתות שנוצרו, בלי להשאיר שאריות.
זרימת העבודה הזאת הופכת את ההרמה של סביבת פיתוח שלמה לפעולה של כמה שניות. מפתח חדש שמצטרף לצוות לא צריך להתקין PostgreSQL, Redis וכל שאר התלויות על המחשב שלו - הוא פשוט מריץ docker compose up וכל הסטאק רץ, בדיוק כמו שהוא אמור לרוץ.
למה זה הכלי הסטנדרטי לפיתוח מקומי¶
היתרון המרכזי של Compose הוא שסביבת הפיתוח המקומית יכולה לשקף בצורה קרובה מאוד את ארכיטקטורת הייצור, בלי שהמפתח צריך להבין את כל פרטי התשתית. אם בייצור האפליקציה רצה מול PostgreSQL ו-Redis, אז גם מקומית היא רצה מול אותם שירותים בדיוק, באותן גרסאות, בלי ש"אצלי זה עבד" יהפוך לתירוץ נפוץ.
זו גם הסיבה שהוא כל כך שימושי לבדיקות - אפשר להרים סביבה מלאה ונקייה, להריץ עליה בדיקות אינטגרציה, ולהוריד אותה לגמרי בסוף, בלי להשאיר אף שריד על המחשב.
מלכודת נפוצה¶
הטעות הכי שכיחה היא לסמוך על volumes בצורה לא נכונה ולגלות שנתונים "נעלמו" אחרי docker compose down -v, כי הדגל הזה מוחק גם את ה-volumes ולא רק את הקונטיינרים. כדאי תמיד להבין את ההבדל בין down הרגיל, שרק עוצר ומסיר קונטיינרים ורשתות, לבין down -v, שמוחק גם את הנתונים השמורים. עוד מלכודת נפוצה היא לשכוח להגדיר depends_on נכון, ואז ה-backend מנסה להתחבר למסד נתונים שעדיין לא סיים לעלות.
מי שרוצה להבין את כל התמונה - איך שירותים, רשתות ותשתית מתחברים יחד בפועל בסביבת שרת אמיתית - מוזמן להעיף מבט על קורס צד שרת.
ברגע שהתרגלתם לעבוד עם Docker Compose, קשה לחזור לניהול קונטיינרים ידני. זה אחד הכלים שהופכים "להרים סביבה" משעה של כאב ראש לפקודה אחת.