ההבדל בין docker compose stop ל-docker compose down
מה ההבדל בין הפקודות? docker compose stop עוצר מכולות ושומר אותן, בעוד docker compose down מוחק מכולות ורשתות. שימו לב: אף אחת מהן לא מוחקת volumes ללא הדגל v--.
התשובה הקצרה
docker compose stop עוצר את המכולות ומשאיר אותן על הדיסק. docker compose down עוצר אותן ולאחר מכן מוחק את המכולות ואת הרשת ש-Compose יצר עבור הפרויקט. אף אחת מהפקודות אינה נוגעת ב-named volume. הוספת -v, כפי שמופיע ב-docker compose down -v, מסירה volumes בעלי שם שאינם חיצוניים, אשר הוגדרו בסעיף volumes בקובץ ה-Compose ושייכים לפרויקט זה. מה ש-down כן משליך הוא כל מידע שהמכולה כתבה לשכבת הכתיבה שלה, מחוץ לכל volume.
זהו כל ההבדל בפסקה אחת. שאר המדריך מוכיח זאת באמצעות volume של Postgres שניתן לראות שורד down ונעלם תחת down -v, ומסביר את שני המקרים שבהם נדרש --force-recreate.
docker compose stop: המכולות נשארות
stop שולח את אות העצירה שהוגדר למכולה, כברירת מחדל SIGTERM, לתהליך הראשי בכל מכולה, ממתין, ואז שולח SIGKILL אם התהליך עדיין פעיל. זמן ההמתנה המוגדר כברירת מחדל הוא 10 שניות, וניתן לשנותו באמצעות -t. דבר אינו נמחק. המכולה שומרת על ה-ID שלה, על שכבת הכתיבה שלה ועל הלוגים שלה.
docker compose stop
docker compose ps -adocker compose ps לבדו מציג רק מכולות פעילות, לכן לאחר stop הוא מדפיס טבלה ריקה, מה שגורם למשתמשים לחשוב שהמכולות נעלמו. ps -a כולל גם מכולות שעצרו, ושם תראו סטטוס Exited לצד כל שירות, יחד עם קוד היציאה שהתהליך החזיר. כיבוי תקין מציג לרוב Exited (0), אך לא תמיד. שרתים מסוימים מסיימים כיבוי מסודר ואז מעלים מחדש את אות העצירה כך שהתהליך מסתיים בעקבותיו; Uvicorn פועל בדיוק כך, לכן עצירה מסודרת עדיין יכולה להניב קוד שאינו אפס. קוד שאינו אפס יכול גם להעיד על כך שהתהליך נכשל או נהרג לאחר פקיעת זמן ההמתנה. החזירו אותן לפעילות באמצעות docker compose start, שמשתמש מחדש באותן מכולות בדיוק.
מכיוון שהמכולות עדיין קיימות, כל מה שנכתב בתוכן מחוץ ל-volume נשאר שם. זה כולל חבילה שהתקנתם ידנית באמצעות docker compose exec, וקובץ תצורה שערכתם בתוך המכולה. זו הסיבה המעשית להעדיף את stop בזמן ניפוי שגיאות (debugging): ניתן לבצע הפעלה מחדש לאותו מצב בדיוק.
docker compose down: הסרת מכולות ורשתות
down עוצר את המכולות ומסיר אותן, יחד עם הרשת המוגדרת כברירת מחדל שנוצרה עבור הפרויקט. התיעוד של Docker מתאר זאת כעצירה והסרה של מכולות, רשתות, volumes ואימג'ים שנוצרו על ידי up, אך החלקים של ה-volumes והאימג'ים מתבצעים רק כאשר מבקשים זאת במפורש באמצעות -v ו---rmi.
docker compose down
docker compose ps -a
docker network lsלאחר down, הפקודה ps -a לא תציג דבר עבור הפרויקט והרשת <project>_default תוסר. שם הפרויקט נגזר משם תיקיית הפרויקט, אלא אם הגדרתם name: בקובץ ה-Compose, הגדרתם COMPOSE_PROJECT_NAME, או העברתם את הדגל -p. כל שינוי שביצעתם בתוך שכבת הכתיבה של המכולה אינו ניתן לשחזור, לכן יש להתייחס ל-down כאל פקודה שמוחקת את המכולה ושומרת רק את הנתונים שנמצאים בתוך ה-volumes.
אם Compose לא מוצא קובץ הגדרות בתיקייה הנוכחית או בתיקיות האב שלה, ולא סיפקתם קובץ כזה באמצעות -f או COMPOSE_FILE, תקבלו את השגיאה 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 שאליו הוא היה מחובר. זהו החשש הנפוץ ביותר בנוגע לפקודה זו. גרסה 5.7.0 של Compose שינתה את down -v: כעת היא מדלגת על volumes בעלי שם השייכים לפרויקט אחר או שנוצרו מחוץ ל-Compose, תוך הצגת אזהרה.
הגדירו 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:הפעילו את ה-stack וכתבו שורה שתוכלו לזהות מאוחר יותר.
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 מכסה את ההבדלים בין volumes בעלי שם לבין bind mounts, ומסביר היכן כל אחד מהם מאוחסן בפועל על ה-host.
מה בדיוק מוחק הפקודה down -v
-v (הצורה המלאה --volumes) מסירה volumes בעלי שם שאינם חיצוניים, אשר הוגדרו בסעיף volumes בקובץ ה-Compose ושייכים לפרויקט הנוכחי, בנוסף ל-volumes אנונימיים המחוברים למכולות. בגרסה Compose v5.7.0, volume בעל שם שנושא תווית בעלות של פרויקט אחר או שאין לו תווית פרויקט כלל, ידלג על המחיקה ויוצג אזהרה; אם לא ניתן לבדוק את הבעלות עליו, הפקודה תיכשל וה-volume יישמר. יש להריץ את הפקודה מול אותו ה-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 שרץ במשך חודשים משמעותה ש-Postgres מאתחל ספריית נתונים ריקה. טבלת ה-marker שלכם נמחקה, והדרך היחידה לשחזר אותה היא מגיבוי.
אחסון מסוים לעולם אינו מוסר על ידי -v. Bind mount הוא נתיב במערכת המארחת, לכן Docker רק מבצע לו unmount והקבצים נשארים במקומם. Volume המסומן כ-external: true מוגדר כשייך למשהו מחוץ לפרויקט זה, ו-Compose לעולם לא יסיר אותו. Volume בעל שם שמחקתם מקובץ ה-Compose לפני הרצת down -v אינו מוגדר עוד, לכן Compose אינו יודע שעליו להסירו, והוא נשאר כיתום עבור docker volume prune -a ברגע שאף מכולה לא מפנה אליו.
המקרה האחרון תופס משתמשים לא מוכנים במהלך ביצוע refactor. אם תסירו שירות וה-volume שלו מהקובץ ותריצו down -v, ה-volume ישרוד כיוון שהקובץ כבר לא מזכיר אותו. הריצו את down -v לפני עריכת הקובץ, ולא אחריה.
מתי באמת נדרש השימוש ב- --force-recreate
docker compose up -d לא בונה מחדש את כל הסביבה בכל פעם. Compose שומר hash של התצורה המפוענחת של כל שירות כתווית (label) על גבי המכולה. בגרסה Compose v5.7.0, מכולה פעילה נותרת ללא שינוי כאשר ה-hash של התצורה, מזהה ה-image וה-digest של ה-image-volume תואמים, כאשר חיבורי הרשת ונקודות ה-mount של ה-volumes המוגדרים קיימים, וכאשר אין תלות ב-namespace או ב-volume-sharing שדורשת יצירה מחדש. אתם מקבלים Container voltest-db-1 Running במקום Recreated. זהו ההתנהגות הרצויה ברוב המוחלט של המקרים, כיוון שהיא הופכת את up -d לבטוח להרצה חוזרת.
זו גם הסיבה לכך שחלק מהעריכות נראות כאילו אינן משפיעות. Compose מבצע hash להגדרת השירות המפוענחת, ולא לתוכן הקבצים שאליהם ההגדרה מצביעה. קובץ תצורה שמוגדר ב-mount לתוך המכולה ונקרא פעם אחת בעת העלייה, לא יפעיל יצירה מחדש (recreate) כאשר תערכו אותו, כיוון שנתיב ה-mount לא השתנה. השירות ממשיך לרוץ עם הערכים שקרא בעת ה-boot.
docker compose up -d --force-recreateפקודה זו עוצרת ומסירה כל מכולה ויוצרת אחת חדשה על פי אותה הגדרה. השתמשו בה לאחר עריכה של קובץ תצורה ב-mount, או כאשר מכולה הגיעה למצב לא מוסבר. ה-volumes נותרים ללא שינוי, כך ש-database שורד יצירה מחדש בכוח. כדי להשתמש ב-image חדש יותר תחת אותו תג (tag), עליכם לבצע גם pull.
docker compose pull
docker compose up -dpull מושך את מזהה ה-image החדש, ו-up -d מזהה לאחר מכן מזהה image שונה מזה של המכולה הפעילה ומבצע יצירה מחדש באופן אוטומטי. הוספת --force-recreate ללא ה-pull תייצר מכולה חדשה מאותו image ישן. זו הסיבה לכך ש-"ביצעתי force recreate ועדיין מדובר בגרסה הישנה" היא תלונה נפוצה כל כך.
docker compose restart לא מבצע אף אחת מפעולות אלו. הוא מאתחל את המכולות הקיימות מבלי להחיל שינויים בתצורה שלהן, לכן משתנה סביבה (environment variable) ששונה או מיפוי פורטים שהשתנה לא יחולו. אם ערכתם את הקובץ, השתמשו ב-up -d.
מודל מנטלי לעבודה
מכולות (containers) הן רכיבים ברי-החלפה. מכולה היא תהליך בתוספת שכבת כתיבה דקה, ו-Compose יכול ליצור מכולה חלופית מתוך הקובץ וה-image. כרכים (volumes) אינם ברי-החלפה, כיוון שהם מחזיקים את העותק היחיד של המידע ששום קובץ במאגר (repository) שלכם לא יכול לשחזר.
כל פקודה ב-Compose תואמת להפרדה הזו. stop ו-start שומרים על המכולה. down ו-up מחליפים את המכולה ושומרים על הכרך. down -v היא הפקודה השגרתית היחידה שמוחקת את המידע, וזו הסיבה שהיא דורשת flag מפורש. לפני הרצת הפקודה על סביבה חיה, ודאו שיש לכם גיבוי ששוחזר בהצלחה לפחות פעם אחת.
אותו היגיון חל על secrets. סיסמה שנקבעת דרך POSTGRES_PASSWORD משמשת רק להגדרת סיסמת מסד הנתונים בעת האתחול הראשוני שלו. לכן, שינוי הסיסמה בקובץ ה-environment והרצת up -d לא ישנו את הסיסמה השמורה במסד הנתונים. המכולה חדשה אך הכרך נשאר ישן, והכרך הישן עדיין מחזיק בסיסמה הישנה. כיצד Compose פותר קובצי env ו-secrets מסביר איזו שכבה גוברת כאשר אותו משתנה מוגדר פעמיים.
מצבי כשל והודעות שיופיעו
no configuration file provided: not found מציין ש-Compose לא הצליח למצוא קובץ תצורה בחיפוש בתיקייה הנוכחית או בתיקיות האב, -f, או COMPOSE_FILE. יש להעביר את הדגל -f עם הנתיב המלא.
Network voltest_default Resource is still in use ב-down בגרסת Compose v5.7.0 מציין שמכולות עדיין מחוברות לרשת הפרויקט, בדרך כלל מכולות מחוץ לפרויקט זה שהופעלו ידנית באמצעות docker run --network. יש להסיר את המכולות הללו ולאחר מכן להריץ שוב את down.
Found orphan containers (voltest-old-1) for this project מופיע לאחר שינוי שם או מחיקה של שירות. גרסאות Compose נוכחיות מציגות את השמות ללא תוספות ומופרדים בפסיקים. גרסאות Compose v2 ישנות יותר מדפיסות את אותה אזהרה עם השמות בתוך סוגריים מרובעים, כפי שמופיע ב-([voltest-old-1]). המכולה הישנה עדיין נושאת את תווית הפרויקט. 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 מסירה volumes בעלי שם שאינם מוגדרים כ-external, אשר הוצהרו בסעיף volumes בקובץ ה-Compose ושייכים לפרויקט זה.
מה ההבדל בין stop לבין down עבור מכולה שאני רוצה להחזיר?
הפקודה stop שומרת על המכולה, לכן docker compose start מחזירה אותך לאותה מכולה בדיוק עם אותה שכבת כתיבה (writable layer). כל מה שהתקנת או ערכת בתוך המכולה באופן ידני יישאר שם. הפקודה down מוחקת את המכולה, לכן הפקודה up -d הבאה תבנה מכולה חדשה מה-image וכל השינויים הידניים יאבדו. בזמן ניפוי שגיאות (debugging), השתמש ב-stop.
איך אני מסיר את כל מה שפרויקט Compose יצר?
הפקודה docker compose down -v --rmi all --remove-orphans מסירה את המכולות, את רשת הפרויקט, את ה-volumes בעלי השם שאינם external שהוצהרו בקובץ ושייכים לפרויקט, את ה-images שבהם השתמשו השירותים, ואת מכולות היתום (orphan containers) של הפרויקט. היא אינה נוגעת ב-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.