ההבדל בין docker compose stop ל-docker compose down
מה ההבדל בין docker compose stop ל-docker compose down? הפקודה stop עוצרת קונטיינרים, בעוד down מוחקת אותם ואת הרשת. אף אחת לא מוחקת volumes אלא אם משתמשים בדגל v--.
התשובה הקצרה
docker compose stop עוצר את הקונטיינרים ומשאיר אותם על הדיסק. docker compose down עוצר אותם ולאחר מכן מוחק את הקונטיינרים ואת הרשת ש-Compose יצר עבור הפרויקט. אף אחת מהפקודות הללו אינה נוגעת ב-volumes בעלי שם. בסיס הנתונים שלך נמחק רק כאשר מוסיפים את -v, כפי שמופיע ב-docker compose down -v, אשר מסיר את ה-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 כאל פקודה שמוחקת את הקונטיינר ושומרת רק את הנתונים שהצבת בתוך כרכים.
הרצת הפקודה בספרייה הלא נכונה תניב no configuration file provided: not found. ל-Compose אין מידע על הפרויקט אליו התכוונת, ולכן הפעולה נדחית. השתמש ב-docker compose -f /srv/myapp/compose.yaml down כאשר אינך נמצא בתיקיית הפרויקט.
האם הפקודה docker compose down מוחקת את הכרכים (Volumes) שלי?
לא. כרך בעל שם (named volume) שמוגדר תחת מפתח הרמה העליונה volumes שורד את down, והוא שורד גם את הקונטיינר שאליו הוא היה מחובר. זהו החשש הנפוץ ביותר בנוגע לפקודה זו, והתשובה נותרת יציבה לאורך גרסאות Compose v2.
הגדר סטאק שתוכל לבצע מולו בדיקות. הכנס את התוכן הבא לתוך 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');"כעת השמד את הקונטיינר ובדוק את הכרך.
docker compose down
docker volume lsהפלט עדיין מציג את voltest_pgdata. הקונטיינר הוסר אך הנתונים נותרו. החזר את הסטאק לפעולה וקרא את השורה.
docker compose up -d
sleep 10
docker compose exec -T db psql -U postgres -c "select * from marker;"תקבל שורה אחת המכילה את survived. הקונטיינר החדש הוא קונטיינר שונה בעל מזהה (ID) שונה, המחובר לאותו הכרך. אם ברצונך לקבל תמונה רחבה יותר, מדריך היסודות של Compose מכסה כרכים בעלי שם לעומת bind mounts ומסביר היכן כל אחד מהם באמת מאוחסן במארח (host).
מה בדיוק מבצעת הפקודה down -v
הפקודה -v (בצורתה המלאה --volumes) מסירה את הכרכים (volumes) בעלי השם שהוגדרו בסעיף volumes בקובץ ה-Compose, בנוסף לכרכים אנונימיים המחוברים לקונטיינרים. הרץ אותה על אותו ה-stack.
docker compose down -v
docker volume lsהערך voltest_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 שרץ במשך חודשים משמעותה שהכרך הוסר. טבלת ה-marker שלך אבדה, והדרך היחידה לשחזר אותה היא מתוך גיבוי.
אחסון מסוים לעולם אינו מוסר על ידי -v. חיבור מסוג bind mount הוא נתיב במערכת המארחת (host), לכן Docker רק מבצע לו unmount והקבצים שלך נשארים במקומם. כרך המסומן כ-external: true מוגדר כשייך למשהו מחוץ לפרויקט זה, ו-Compose לעולם אינו מסיר אותו. כרך בעל שם שמחקת מקובץ ה-Compose לפני הרצת down -v אינו מוגדר עוד, לכן Compose אינו יודע שעליו להסירו והוא נותר מאחור כיתום עבור docker volume prune.
המקרה האחרון תופס משתמשים לא מוכנים במהלך תהליך refactor. אם תסיר שירות ואת הכרך שלו מהקובץ ותריץ down -v, הכרך ישרוד מכיוון שהקובץ אינו מזכיר אותו עוד. הרץ down -v לפני עריכת הקובץ, לא אחריה.
מתי באמת נדרש השימוש ב-force-recreate--
docker compose up -d אינו מבצע בנייה מחדש של כל המערכת בכל פעם. Compose שומר גיבוי (hash) של ההגדרה המפוענחת של כל שירות כתווית (label) על גבי הקונטיינר. אם הגיבוי תואם ומזהה האימג' (image ID) תואם, הקונטיינר נשאר ללא שינוי ואתה מקבל Container voltest-db-1 Running במקום Recreated. זוהי ההתנהגות הרצויה ברוב המוחלט של המקרים, שכן היא מאפשרת להריץ את up -d שוב ושוב בבטחה.
זו גם הסיבה לכך שחלק מהשינויים נראים כאילו אינם משפיעים. Compose מבצע גיבוי להגדרת השירות המפוענחת, ולא לתוכן הקבצים שאליהם ההגדרה מצביעה. קובץ הגדרות שממופה (mounted) לתוך הקונטיינר ונקרא פעם אחת בעת העלייה, לא יפעיל יצירה מחדש בעת עריכתו, כיוון שנתיב המיפוי לא השתנה. השירות ממשיך לרוץ עם הערכים שקרא בעת האתחול.
docker compose up -d --force-recreateפקודה זו עוצרת ומסירה כל קונטיינר ויוצרת אחד חדש על פי אותה הגדרה. השתמש בה לאחר עריכת קובץ הגדרות ממופה, או כאשר קונטיינר הגיע למצב לא מוסבר. הווליומים (volumes) נשארים ללא שינוי, כך שבסיס נתונים שורד יצירה מחדש בכוח. כדי להחיל אימג' חדש יותר תחת אותו תג (tag), עליך לבצע גם משיכה (pull).
docker compose pull
docker compose up -dpull מושך את מזהה האימג' החדש, ו-up -d מזהה לאחר מכן מזהה אימג' שונה מזה של הקונטיינר הרץ ומבצע יצירה מחדש באופן עצמאי. הוספת --force-recreate ללא pull תייצר עבורך קונטיינר חדש מאותו אימג' ישן. זו הסיבה לכך שהתלונה "ביצעתי יצירה מחדש בכוח ועדיין מדובר בגרסה הישנה" היא נפוצה כל כך.
docker compose restart אינו מבצע אף אחת מפעולות אלו. הוא מאתחל את הקונטיינרים הקיימים ואינו קורא מחדש את קובץ ה-Compose כלל, לכן שינוי במשתנה סביבה או במיפוי פורטים לא יוחל. אם ערכת את הקובץ, השתמש ב-up -d.
המודל המחשבתי שיש לאמץ
קונטיינרים הם ברי-החלפה. קונטיינר הוא תהליך בתוספת שכבת כתיבה דקה, ו-Compose יכול לבנות אחד זהה מתוך הקובץ בתוך כשנייה. נפחים (Volumes) אינם ברי-החלפה, כיוון שהם מחזיקים את העותק היחיד של המצב (state) שאף קובץ במאגר שלכם אינו יכול לשחזר.
כל פקודה ב-Compose תואמת לחלוקה הזו. stop ו-start שומרים על הקונטיינר. down ו-up מחליפים את הקונטיינר ושומרים על הנפח. down -v היא הפקודה השגרתית היחידה שמוחקת את המצב, וזו הסיבה שהיא דורשת דגל מפורש. לפני שתקלידו אותה על סביבה אמיתית כלשהי, ודאו שיש לכם גיבוי ששחזרתם לפחות פעם אחת.
אותו היגיון חל על סודות (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 מנקה אותם, וזה בטוח להרצה על סטאק תקין.
Error response from daemon: remove voltest_pgdata: volume is in use ב-docker volume rm ידני מציין שקונטיינר כלשהו עדיין מפנה לנפח האחסון (volume), כולל קונטיינר שעצור. הרץ תחילה את docker compose down, לאחר מכן הסר את הנפח, או פשוט השתמש ב-down -v. בפרויקט גדול יותר, סטאק 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.