Docker Compose: різниця між down і stop
Дізнайтеся, чим відрізняються docker compose stop і down: stop зберігає контейнери, down видаляє їх і мережу, а named volume не видаляється без --volumes.
Коротка відповідь
docker compose stop зупиняє контейнери й залишає їх на диску. docker compose down зупиняє контейнери, а потім видаляє їх і мережу, яку Compose створив для проєкту. Жодна з цих команд не змінює іменований том. База даних видаляється лише після додавання -v, як у docker compose down -v, що видаляє іменовані томи, оголошені в розділі volumes файлу Compose.
У цьому полягає вся різниця. Далі в цьому посібнику показано її на прикладі тому Postgres, який можна побачити після down і який зникає після down -v. Також пояснено два випадки, коли потрібен --force-recreate.
docker compose stop: контейнери залишаються
stop надсилає SIGTERM головному процесу в кожному контейнері, очікує, а потім надсилає SIGKILL, якщо процес усе ще працює. Типовий час очікування становить 10 секунд, а -t змінює його. Нічого не видаляється. Контейнер зберігає свій ідентифікатор, доступний для запису шар, резервування IP-адреси та журнали.
docker compose stop
docker compose ps -adocker compose ps без аргументів показує лише запущені контейнери, тому після stop виводить порожню таблицю, і користувачі думають, що контейнери зникли. ps -a включає зупинені контейнери, і саме там біля кожного сервісу ви побачите Exited (0). Відновіть їх за допомогою docker compose start — буде повторно використано ті самі контейнери.
Оскільки контейнери все ще існують, усі дані, записані в них за межами volume, зберігаються. Це стосується пакета, який ви встановили вручну за допомогою docker compose exec, а також конфігураційного файла, відредагованого всередині контейнера. Саме тому під час налагодження практично використовувати stop: можна перезапустити застосунок у тому самому стані.
docker compose down: контейнери та мережі видаляються
down зупиняє контейнери, а потім видаляє їх разом із мережею за замовчуванням, яку Compose створив для проєкту. У документації Docker цю команду описано як таку, що зупиняє контейнери та видаляє контейнери, мережі, томи й образи, створені за допомогою 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, існує довше за down і контейнер, до якого його було під’єднано. Це найпоширеніше побоювання щодо цієї команди, але в Compose v2 відповідь незмінна.
Підготуйте стек для перевірки. Створіть порожній каталог із назвою voltest і додайте до compose.yaml такий вміст.
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, а також де кожен із них фактично зберігається на хості.
Що саме знищує down -v
-v (повна форма --volumes) видаляє іменовані томи, оголошені в секції volumes файлу Compose, а також анонімні томи, підключені до контейнерів. Виконуйте команду для того самого стека.
docker compose down -v
docker volume lsvoltest_pgdata більше не відображається у списку. Запустіть стек знову. Тоді entrypoint Postgres виявить порожній каталог даних і ініціалізує новий кластер. У журналі контейнера це чітко зазначено.
The files belonging to this database system will be owned by user "postgres".
PostgreSQL init process complete; ready for start up.Якщо цей блок з’явився у стеку, який працював місяцями, це означає, що том було видалено. Таблицю marker втрачено, і єдиний спосіб відновлення — використати резервну копію.
Деякі сховища -v ніколи не видаляє. Bind mount — це шлях на хості, тому Docker лише відмонтовує його, а ваші файли залишаються на місці. Том із позначкою external: true оголошено таким, що належить чомусь поза межами цього проєкту, тому Compose його не видаляє. Іменований том, який ви видалили з файлу Compose перед запуском down -v, більше не оголошений у файлі. Тому Compose не знає, що його потрібно видалити, і залишає його як осиротілий том для docker volume prune.
Останній випадок часто виникає під час рефакторингу. Видаліть сервіс і його том із файлу, виконайте down -v — і том залишиться, оскільки у файлі більше немає згадки про нього. Виконайте down -v до редагування файлу, а не після.
Коли насправді потрібен --force-recreate
docker compose up -d не перебудовує все під час кожного запуску. Compose зберігає хеш остаточної конфігурації кожного сервісу в контейнері як label. Якщо хеш ідентичний, а ID image збігається, контейнер залишається без змін, і ви отримуєте Container voltest-db-1 Running замість Recreated. Майже завжди потрібна саме така поведінка, оскільки вона робить повторний запуск up -d безпечним.
Саме тому деякі зміни, здається, нічого не роблять. Compose обчислює хеш остаточного опису сервісу, а не вмісту файлів, на які цей опис посилається. Зміна змонтованого в контейнер config file не запускає його повторне створення, якщо файл зчитується лише під час запуску, оскільки шлях монтування не змінився. Сервіс продовжує працювати зі значеннями, які він зчитав під час запуску.
docker compose up -d --force-recreateЦя команда зупиняє та видаляє кожен контейнер, а потім створює новий за тим самим описом. Використовуйте її після зміни змонтованого config file, а також коли контейнер перейшов у стан, причину якого ви не можете пояснити. Volumes не змінюються, тому база даних зберігається після примусового створення контейнера. Щоб отримати новішу image з тим самим tag, потрібно також виконати pull.
docker compose pull
docker compose up -dpull отримує новий ID image, після чого up -d бачить, що ID image відрізняється від ID запущеного контейнера, і самостійно створює контейнер заново. Якщо додати --force-recreate без pull, ви отримаєте новий контейнер на основі тієї самої старої image. Тому скарга «я примусово створив контейнер заново, але це все ще стара версія» трапляється так часто.
docker compose restart не виконує нічого з переліченого. Вона перезапускає наявні контейнери й взагалі не перечитує Compose file, тому змінна середовища або mapping порту не застосуються. Якщо ви змінили файл, використовуйте up -d.
Ментальна модель
Контейнери можна замінити. Контейнер — це процес із тонким доступним для запису шаром, і Compose може приблизно за секунду створити ідентичний контейнер із файлу. Томи не можна просто замінити, оскільки саме вони містять єдину копію стану, яку не можна відновити з жодного файлу у вашому репозиторії.
Кожна команда Compose відповідає цьому поділу. stop і start зберігають контейнер. down і up замінюють контейнер, але зберігають том. down -v — єдина штатна команда, яка видаляє стан, тому для неї потрібен явний прапорець. Перш ніж виконувати її в робочому середовищі, переконайтеся, що маєте резервну копію та хоча б один раз успішно відновили з неї дані.
Та сама логіка діє для секретів. Пароль, заданий через 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 означає, що на том усе ще посилається певний контейнер, зокрема зупинений. Спочатку виконайте docker compose down, а потім видаліть том або просто скористайтеся down -v. У більшому проєкті стек Compose із кількома сервісами показує, скільки томів може накопичити один проєкт.
FAQ
Чи видаляє docker compose down мою базу даних?
Ні, якщо база даних зберігається в іменованому томі або bind mount. down видаляє контейнери та мережу проєкту, а том залишається на диску разом із даними. Наступний запуск docker compose up -d підключає новий контейнер до того самого тому, і дані залишаються доступними. Лише docker compose down -v видаляє іменовані томи, причому тільки ті, що оголошені в секції volumes файлу Compose.
У чому різниця між stop і down для контейнера, який я хочу запустити знову?
stop зберігає контейнер, тому docker compose start повертає вас до того самого контейнера з тим самим доступним для запису шаром. Усе, що ви вручну встановили або змінили всередині контейнера, залишається. down видаляє контейнер, тому наступний запуск up -d створює новий контейнер з образу, і ці ручні зміни втрачаються. Під час налагодження використовуйте stop.
Як видалити все, що створив проєкт Compose?
docker compose down -v --rmi all --remove-orphans видаляє контейнери, мережу проєкту, іменовані томи, оголошені у файлі, образи, які використовували сервіси, а також усі контейнери з міткою, що містить назву проєкту. Команда не видаляє bind mount або томи, позначені external: true. Перед виконанням перевірте, що саме буде видалено, за допомогою docker volume ls.
Чому мій контейнер не враховує зміни, внесені до змонтованого конфігураційного файлу?
Compose визначає, чи потрібно повторно створити контейнер, порівнюючи хеш розгорнутого опису сервісу. Вміст змонтованого файлу до цього хешу не входить. Шлях не змінився, тому Compose залишає контейнер запущеним зі значеннями, прочитаними під час запуску. Виконайте docker compose up -d --force-recreate, щоб створити новий контейнер, який повторно прочитає файл.
Чому нове значення POSTGRES_PASSWORD не працює після зміни?
Образ Postgres читає POSTGRES_PASSWORD лише під час ініціалізації порожнього каталогу даних. У вашому томі вже є ініціалізований кластер, тому змінну проігноровано, а старий пароль залишається чинним. Ви побачите password authentication failed for user "postgres". Змініть пароль за допомогою ALTER USER у запущеній базі даних або погодьтеся на втрату даних і почніть спочатку за допомогою docker compose down -v.