Docker Compose stop לעומת down: מה ההבדל?
מה ההבדל בין הפקודות docker compose stop ו-down? המדריך מסביר אילו מכולות נמחקות, מה קורה לרשת הפרויקט ומתי המידע ב-named volumes שלכם באמת נמצא בסכנת מחיקה.
התשובה הקצרה
docker compose stop עוצר את המכולות ומשאיר אותן על הדיסק. docker compose down עוצר אותן ולאחר מכן מוחק את המכולות ואת הרשת ש-Compose יצר עבור הפרויקט. אף אחת מהפקודות אינה נוגעת ב-named volume. מסד הנתונים שלכם יושמד רק כאשר תוסיפו -v, כפי שמופיע ב-docker compose down -v, אשר מסיר את ה-named volumes שהוגדרו בסעיף volumes בקובץ ה-Compose.
זהו כל ההבדל בפסקה אחת. שאר המדריך מוכיח זאת באמצעות volume של Postgres שניתן לראות שורד down ונעלם תחת down -v, ומסביר את שני המקרים שבהם נדרש --force-recreate.
docker compose stop: המכולות נשארות
stop שולח אות SIGTERM לתהליך הראשי בכל מכולה, ממתין, ולאחר מכן שולח SIGKILL אם התהליך עדיין פעיל. זמן ההמתנה המוגדר כברירת מחדל הוא 10 שניות, וניתן לשנות אותו באמצעות -t. דבר אינו נמחק. המכולה שומרת על ה-ID שלה, על שכבת הכתיבה, על כתובת ה-IP שהוקצתה לה ועל הלוגים שלה.
docker compose stop
docker compose ps -adocker compose ps מציג כברירת מחדל רק מכולות פעילות, לכן לאחר stop הוא מדפיס טבלה ריקה, מה שגורם למשתמשים לחשוב שהמכולות נמחקו. ps -a כולל גם מכולות שעצרו, ושם תראו את Exited (0) לצד כל שירות. ניתן להחזיר אותן לפעילות באמצעות docker compose start, אשר עושה שימוש חוזר באותן מכולות בדיוק.
מכיוון שהמכולות עדיין קיימות, כל מידע שנכתב בתוכן מחוץ ל-volume נשאר כשהיה. זה כולל חבילות שהתקנתם ידנית באמצעות docker compose exec, וקובצי תצורה שערכתם בתוך המכולה. זו הסיבה המעשית להעדיף את stop בזמן ניפוי שגיאות (debugging): ניתן לבצע הפעלה מחדש לאותו מצב בדיוק.
docker compose down: הסרת מכולות ורשתות
down עוצר את המכולות ומסיר אותן, יחד עם רשת ברירת המחדל ש־Compose יצר עבור הפרויקט. התיעוד של Docker מתאר זאת כעצירה והסרה של מכולות, רשתות, כרכים (volumes) ותמונות שנוצרו על ידי up, אך הסרת הכרכים והתמונות מתבצעת רק כאשר מבקשים זאת במפורש באמצעות -v ו־--rmi.
docker compose down
docker compose ps -a
docker network lsלאחר הרצת down, הפקודה ps -a לא תציג דבר עבור הפרויקט והרשת <project>_default תוסר. שם הפרויקט נגזר משם הספרייה, אלא אם הגדרתם name: בקובץ ה-Compose או העברתם את הדגל -p. כל שינוי שביצעתם בתוך השכבה הניתנת לכתיבה של המכולה אינו ניתן לשחזור כעת, לכן התייחסו ל-down כאל פקודה שמוחקת את המכולה ושומרת רק את הנתונים שהצבתם בתוך כרכים (volumes).
הרצת הפקודה בספרייה הלא נכונה תניב no configuration file provided: not found. ל-Compose אין דרך לדעת לאיזה פרויקט התכוונתם, ולכן הוא מסרב לבצע את הפעולה. השתמשו ב-docker compose -f /srv/myapp/compose.yaml down כאשר אינכם נמצאים בתיקיית הפרויקט.
האם הפקודה docker compose down מוחקת את ה-volumes שלי?
לא. volume בעל שם שמוגדר תחת מפתח ה-top level volumes שורד את הפקודה down, והוא שורד גם את ה-container שאליו הוא היה מחובר. זהו החשש הנפוץ ביותר בנוגע לפקודה זו, והתשובה לכך יציבה לאורך כל גרסאות Compose v2.
הקימו stack שתוכלו לבדוק מולו. הציבו את התוכן הבא בתוך compose.yaml בתוך ספרייה ריקה בשם voltest.
services:
db:
image: postgres:16.4
restart: unless-stopped
environment:
POSTGRES_PASSWORD: example
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:הפעילו אותו וכתבו שורה שתוכלו לזהות מאוחר יותר.
docker compose up -d
sleep 10
docker compose exec -T db psql -U postgres -c "create table marker (note text);"
docker compose exec -T db psql -U postgres -c "insert into marker values ('survived');"כעת השמידו את ה-container ובדקו את ה-volume.
docker compose down
docker volume lsהפלט עדיין מציג את voltest_pgdata. ה-container איננו והנתונים נשארו. החזירו את ה-stack וקראו את השורה.
docker compose up -d
sleep 10
docker compose exec -T db psql -U postgres -c "select * from marker;"תקבלו שורה אחת המכילה את survived. ה-container החדש הוא container שונה בעל ID שונה, המחובר לאותו ה-volume. אם ברצונכם לקבל תמונה רחבה יותר, מדריך היסודות של Compose מכסה את ההבדלים בין named volumes לבין bind mounts ומסביר היכן כל אחד מהם באמת מאוחסן על ה-host.
מה בדיוק הפקודה down -v משמידה
-v (הצורה המלאה --volumes) מסירה את ה-volumes בעלי השם שהוגדרו בסעיף volumes בקובץ ה-Compose, בנוסף ל-volumes אנונימיים שמחוברים למכולות. הריצו אותה על אותו ה-stack.
docker compose down -v
docker volume lsvoltest_pgdata לא מופיע יותר ברשימה. הפעילו את ה-stack מחדש, וה-entrypoint של Postgres ימצא ספריית נתונים ריקה ויאתחל cluster חדש. לוג המכולה מציין זאת במפורש.
The files belonging to this database system will be owned by user "postgres".
PostgreSQL init process complete; ready for start up.הופעת בלוק כזה ב-stack שרץ במשך חודשים משמעותה שה-volume הוסר. טבלת ה-marker שלכם אבדה, והדרך היחידה לשחזר היא באמצעות גיבוי.
אחסון מסוים לעולם אינו מוסר על ידי -v. ה-bind mount הוא נתיב במערכת המארחת, לכן Docker רק מבצע לו unmount והקבצים שלכם נשארים במקומם. volume שמסומן כ-external: true מוגדר כשייך למשהו מחוץ לפרויקט הזה, ו-Compose לעולם לא יסיר אותו. volume בעל שם שמחקתם מקובץ ה-Compose לפני הרצת down -v אינו מוגדר יותר, לכן Compose לא יודע שעליו להסיר אותו והוא נשאר מאחור כ-orphan עבור docker volume prune.
המקרה האחרון הזה תופס אנשים במהלך refactor. אם תסירו שירות ואת ה-volume שלו מהקובץ ותריצו down -v, ה-volume ישרוד כיוון שהקובץ כבר לא מזכיר אותו. הריצו down -v לפני עריכת הקובץ, לא אחרי.
מתי באמת צריך להשתמש ב- --force-recreate
docker compose up -d לא בונה מחדש את כל הסביבה בכל פעם. Docker Compose שומר hash של התצורה המפוענחת של כל שירות כ-label על גבי המכולה. אם ה-hash תואם וגם ה-image ID תואם, המכולה נשארת כפי שהיא ואתם מקבלים Container voltest-db-1 Running במקום Recreated. זו ההתנהגות הרצויה ברוב המוחלט של המקרים, שכן היא הופכת את up -d לבטוח להרצה חוזרת.
זו גם הסיבה לכך ששינויים מסוימים נראים כאילו לא השפיעו. Docker Compose מבצע hash להגדרת השירות המפוענחת, ולא לתוכן הקבצים שאליהם ההגדרה מצביעה. קובץ תצורה שממופה (mount) לתוך המכולה ונקרא פעם אחת בעת העלייה, לא יגרום ליצירה מחדש (recreate) בעת עריכתו, כיוון שנתיב ה-mount לא השתנה. השירות ממשיך לרוץ עם הערכים שקרא בעת האתחול.
docker compose up -d --force-recreateפקודה זו עוצרת ומסירה כל מכולה ויוצרת אחת חדשה על פי אותה הגדרה. השתמשו בה לאחר עריכת קובץ תצורה ממופה, או כאשר מכולה הגיעה למצב לא תקין שאינכם מצליחים להסביר. ה-volumes נשארים ללא שינוי, כך שמסד נתונים שורד יצירה מחדש בכוח. כדי להחיל image חדש יותר באותו תג (tag), עליכם לבצע גם pull.
docker compose pull
docker compose up -dpull מושך את ה-image ID החדש, ו-up -d מזהה לאחר מכן שה-image ID שונה מזה של המכולה הרצה ומבצע יצירה מחדש באופן עצמאי. הוספת --force-recreate ללא ה-pull תייצר מכולה חדשה מאותו image ישן. זו הסיבה לכך ש-"ביצעתי יצירה מחדש בכוח ועדיין מדובר בגרסה הישנה" היא תלונה נפוצה כל כך.
docker compose restart לא מבצע אף אחת מפעולות אלו. הוא מאתחל את המכולות הקיימות ולא קורא מחדש את קובץ ה-Compose כלל, לכן שינוי במשתנה סביבה או במיפוי פורטים לא יחול. אם ערכתם את הקובץ, השתמשו ב-up -d.
המודל המחשבתי שיש לאמץ
מכולות (containers) הן רכיבים ברי-החלפה. מכולה היא תהליך בתוספת שכבת כתיבה דקה, ו-Compose יכול לבנות מכולה זהה מתוך הקובץ בשנייה אחת בערך. כוננים (volumes) אינם ברי-החלפה, כיוון שהם מחזיקים את העותק היחיד של המצב (state) ששום קובץ במאגר (repository) שלך לא יכול לשחזר.
כל פקודה ב-Compose תואמת להפרדה הזו. stop ו-start שומרות על המכולה. down ו-up מחליפות את המכולה ושומרות על הכונן. down -v היא הפקודה השגרתית היחידה שמסירה את המצב, וזו הסיבה שהיא דורשת דגל (flag) מפורש. לפני שתקליד אותה על סביבה אמיתית, ודא שיש לך גיבוי ששחזרת לפחות פעם אחת.
אותו היגיון חל על סודות (secrets). סיסמה שנקבעת באמצעות POSTGRES_PASSWORD נקראת רק בפעם הראשונה שבה מסד הנתונים מבצע אתחול, לכן שינוי שלה בקובץ הסביבה והרצת up -d יביאו ל-password authentication failed for user "postgres". המכולה חדשה והכונן ישן, והכונן הישן עדיין מחזיק בסיסמה הישנה. כיצד Compose פותר קובצי סביבה וסודות מסביר איזו שכבה גוברת כאשר אותו משתנה מוגדר פעמיים.
מצבי כשל והודעות שתיתקל בהן
no configuration file provided: not found מציין ש-Compose מורץ בתיקייה שאין בה compose.yaml ואין בה docker-compose.yml. העבר את -f עם הנתיב המלא.
network voltest_default has active endpoints על down מציין שמכולה מחוץ לפרויקט זה מחוברת לרשת הפרויקט, בדרך כלל מכולה שהופעלה ידנית באמצעות docker run --network. הסר את המכולה הזו, ולאחר מכן הרץ שוב את down.
Found orphan containers ([voltest-old-1]) for this project מופיע לאחר שינוי שם או מחיקה של שירות. המכולה הישנה עדיין נושאת את תווית הפרויקט. docker compose down --remove-orphans מנקה אותן, וזה בטוח להרצה על stack תקין.
Error response from daemon: remove voltest_pgdata: volume is in use בביצוע ידני של docker volume rm מציין שמכולה כלשהי עדיין מפנה לנפח האחסון (volume), כולל מכולה שעצרה. הרץ תחילה את docker compose down, לאחר מכן הסר את הנפח, או פשוט השתמש ב-down -v. בפרויקט גדול יותר, stack של Compose עם כמה שירותים מראה כמה נפחי אחסון פרויקט אחד יכול לצבור.
FAQ
האם הפקודה docker compose down מוחקת את מסד הנתונים שלי?
לא, אם מסד הנתונים מאוחסן ב-named volume או ב-bind mount. הפקודה down מסירה את המכולות ואת רשת הפרויקט, אך ה-volume נשאר על הדיסק עם הנתונים בתוכו. הפקודה docker compose up -d הבאה תחבר מכולה חדשה לאותו ה-volume והנתונים יהיו זמינים. רק הפקודה docker compose down -v מסירה named volumes, ורק כאלו שהוגדרו בסעיף volumes בקובץ ה-Compose.
מה ההבדל בין stop ל-down עבור מכולה שאני רוצה להחזיר?
הפקודה stop שומרת על המכולה, לכן docker compose start מחזירה אותך לאותה מכולה עם אותה שכבת כתיבה. כל מה שהתקנת או ערכת בתוך המכולה באופן ידני נשאר שם. הפקודה down מוחקת את המכולה, לכן up -d הבאה תבנה מכולה חדשה מה-image וכל השינויים הידניים יאבדו. בזמן ניפוי שגיאות (debugging), השתמש ב-stop.
איך אני מסיר את כל מה שפרויקט Compose יצר?
הפקודה docker compose down -v --rmi all --remove-orphans מסירה את המכולות, את רשת הפרויקט, את ה-named volumes שהוגדרו בקובץ, את ה-images שבהם השירותים השתמשו, וכל מכולה שעדיין מתויגת בשם הפרויקט. היא לא נוגעת ב-bind mounts או ב-volumes שמסומנים כ-external: true. בדוק מה עומד להימחק באמצעות docker volume ls לפני ההרצה.
מדוע המכולה שלי מתעלמת משינוי שביצעתי בקובץ תצורה (config file) ממופה?
Compose מחליט אם ליצור מחדש מכולה על ידי השוואת hash של הגדרת השירות, וה-hash הזה לא כולל את תוכן הקובץ הממופה. הנתיב לא השתנה, לכן Compose משאיר את המכולה רצה עם הערכים שקראה בעת העלייה. הרץ את docker compose up -d --force-recreate כדי לבנות מכולה חדשה שתקרא את הקובץ מחדש.
מדוע ה-POSTGRES_PASSWORD החדש שלי לא עובד אחרי ששיניתי אותו?
ה-image של Postgres קורא את POSTGRES_PASSWORD רק כאשר הוא מאתחל ספריית נתונים ריקה. ה-volume שלך כבר מכיל אשכול (cluster) מאותחל, לכן המשתנה מתעלם והסיסמה הישנה נשארת בתוקף. אתה תראה את password authentication failed for user "postgres". שנה את הסיסמה באמצעות ALTER USER בתוך מסד הנתונים הרץ, או קבל את אובדן הנתונים והתחל מחדש עם docker compose down -v.