Docker Compose down чи stop: у чому різниця
Дізнайтеся, чим Docker Compose down відрізняється від stop: контейнери й мережа видаляються, але іменований том зберігається без --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. Ця команда повторно використовує ті самі контейнери.
Оскільки контейнери все ще існують, усі дані, записані в них поза томом, залишаються. Це стосується, зокрема, пакета, який ви встановили вручну за допомогою 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.
Підготуйте стек для перевірки. Запишіть це у 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. Новий контейнер відрізняється від попереднього та має інший ідентифікатор, але підключений до того самого тому. Якщо потрібен ширший огляд, у посібнику з основ Compose описано іменовані томи порівняно з монтуванням bind та розташування кожного з них на хості.
Що саме знищує 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 образу збігається, контейнер залишається без змін, а ви отримуєте Container voltest-db-1 Running замість Recreated. Майже завжди потрібна саме така поведінка, оскільки вона дає змогу безпечно багаторазово запускати up -d.
Саме тому деякі зміни, здається, нічого не роблять. Compose хешує розгорнуте визначення служби, а не вміст файлів, на які це визначення посилається. Файл конфігурації, змонтований у контейнер і прочитаний під час запуску, не спричинить повторного створення контейнера після редагування, оскільки шлях монтування не змінився. Служба продовжує працювати зі значеннями, прочитаними під час запуску.
docker compose up -d --force-recreateЦя команда зупиняє та видаляє кожен контейнер і створює новий із того самого визначення. Використовуйте її після редагування змонтованого файла конфігурації, а також коли контейнер перейшов у стан, причину якого неможливо пояснити. Томи не змінюються, тому база даних зберігається після примусового повторного створення. Щоб отримати новіший образ із тим самим тегом, потрібно також виконати pull.
docker compose pull
docker compose up -dpull отримує ID нового образу, а up -d виявляє, що ID образу відрізняється від ID у запущеного контейнера, і самостійно створює контейнер повторно. Додавання --force-recreate без pull створює новий контейнер із тим самим старим образом. Тому скарга «я примусово створив контейнер повторно, але версія все ще стара» трапляється так часто.
docker compose restart не робить нічого з переліченого. Вона перезапускає наявні контейнери й взагалі не перечитує файл Compose, тому змінна середовища або зіставлення портів, які були змінені, не застосуються. Якщо ви редагували файл, використовуйте 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 мою базу даних?
Ні, якщо база даних зберігається в іменованому томі або змонтованому каталозі. 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 видаляє контейнери, мережу проєкту, іменовані томи, оголошені у файлі, образи, які використовували служби, і будь-який контейнер, якому призначено мітку з назвою проєкту. Команда не змінює змонтовані каталоги або томи, позначені 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.