Docker Compose: różnica między stop a down
stop zachowuje kontenery, down usuwa kontenery i sieć projektu, ale nie nazwany wolumen. Dane usuwa dopiero flaga --volumes, np. docker compose down --volumes.
Krótka odpowiedź
docker compose stop zatrzymuje kontenery i pozostawia je na dysku. docker compose down zatrzymuje kontenery, a następnie usuwa kontenery i sieć Compose utworzoną dla projektu. Żadna z tych komend nie usuwa wolumenu nazwanego. Baza danych zostanie usunięta dopiero po dodaniu -v, jak w docker compose down -v. Ta opcja usuwa nazwane wolumeny zadeklarowane w sekcji volumes pliku Compose.
To cała różnica w jednym akapicie. W dalszej części poradnika zostanie ona pokazana na przykładzie wolumenu Postgres, którego można obserwować podczas przetrwania down i usunięcia przez down -v. Wyjaśnione zostaną również dwa przypadki, w których wymagane jest użycie --force-recreate.
docker compose stop: kontenery pozostają
stop wysyła SIGTERM do głównego procesu w każdym kontenerze, czeka, a następnie wysyła SIGKILL, jeśli proces nadal działa. Domyślny czas oczekiwania wynosi 10 sekund. -t zmienia ten czas. Nic nie jest usuwane. Kontener zachowuje swój identyfikator, zapisywalną warstwę, rezerwację adresu IP oraz dzienniki.
docker compose stop
docker compose ps -adocker compose ps bez argumentów wyświetla tylko uruchomione kontenery, dlatego po wykonaniu stop wyświetlana jest pusta tabela i można uznać, że kontenery zostały usunięte. ps -a uwzględnia również zatrzymane kontenery. W tym miejscu obok każdej usługi będzie widoczny wpis Exited (0). Kontenery można ponownie uruchomić za pomocą docker compose start, które wykorzystuje dokładnie te same kontenery.
Ponieważ kontenery nadal istnieją, wszystko zapisane w ich systemie plików poza wolumenem nadal tam pozostaje. Dotyczy to również pakietu zainstalowanego ręcznie za pomocą docker compose exec oraz pliku konfiguracyjnego zmodyfikowanego wewnątrz kontenera. Jest to praktyczny powód, aby podczas debugowania preferować stop: można ponownie uruchomić kontener w tym samym stanie.
docker compose down: kontenery i sieci są usuwane
down zatrzymuje kontenery, a następnie je usuwa razem z domyślną siecią utworzoną przez Compose dla projektu. Dokumentacja Docker opisuje tę operację jako zatrzymywanie kontenerów i usuwanie kontenerów, sieci, woluminów oraz obrazów utworzonych przez up, ale woluminy i obrazy są usuwane tylko po użyciu opcji -v i --rmi.
docker compose down
docker compose ps -a
docker network lsPo wykonaniu down polecenie ps -a nie wyświetla niczego dla projektu, a sieć <project>_default zostaje usunięta. Nazwa projektu pochodzi z nazwy katalogu, chyba że w pliku Compose ustawiono name: lub przekazano -p. Wszystkie zmiany wprowadzone w zapisywalnej warstwie kontenera są teraz nieodwracalne. Należy traktować down jako polecenie usuwające kontener i zachowujące dane umieszczone w woluminach.
Uruchomienie polecenia w niewłaściwym katalogu powoduje wyświetlenie no configuration file provided: not found. Compose nie wie, który projekt ma zostać użyty, dlatego odmawia wykonania operacji. Użyj docker compose -f /srv/myapp/compose.yaml down, jeśli bieżący katalog nie jest katalogiem projektu.
Czy docker compose down usuwa moje wolumeny?
Nie. Nazwany wolumen zadeklarowany w kluczu najwyższego poziomu volumes pozostaje po wykonaniu down i po usunięciu kontenera, do którego był dołączony. To najczęstsza obawa związana z tym poleceniem. Odpowiedź pozostaje taka sama w Compose v2.
Przygotuj stos do testów. Umieść poniższą zawartość w pliku compose.yaml w pustym katalogu o nazwie voltest.
services:
db:
image: postgres:16.4
restart: unless-stopped
environment:
POSTGRES_PASSWORD: example
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:Uruchom stos i zapisz wiersz, który będzie można później rozpoznać.
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');"Usuń teraz kontener i sprawdź wolumen.
docker compose down
docker volume lsDane wyjściowe nadal zawierają voltest_pgdata. Kontener został usunięty, ale dane pozostały. Ponownie uruchom stos i odczytaj zapisany wiersz.
docker compose up -d
sleep 10
docker compose exec -T db psql -U postgres -c "select * from marker;"Zostanie zwrócony jeden wiersz zawierający survived. Nowy kontener jest innym kontenerem i ma inny identyfikator, ale jest dołączony do tego samego wolumenu. Szersze omówienie zawiera przewodnik po podstawach Compose, w którym porównano nazwane wolumeny z montowaniami bind mount oraz wyjaśniono, gdzie każdy z tych typów danych znajduje się na hoście.
Co dokładnie usuwa down -v
-v (dłuższa forma --volumes) usuwa nazwane wolumeny zadeklarowane w sekcji volumes pliku Compose, a także wolumeny anonimowe dołączone do kontenerów. Należy wykonać to polecenie dla tego samego stosu.
docker compose down -v
docker volume lsvoltest_pgdata nie jest już wyświetlany na liście. Po ponownym uruchomieniu stosu punkt wejścia Postgresa znajduje pusty katalog danych i inicjalizuje nowy klaster. Dziennik kontenera informuje o tym wprost.
The files belonging to this database system will be owned by user "postgres".
PostgreSQL init process complete; ready for start up.Pojawienie się tego bloku w stosie działającym od kilku miesięcy oznacza, że wolumen został usunięty. Tabela marker zniknęła, a jedynym sposobem jej odzyskania jest przywrócenie kopii zapasowej.
Niektóre dane pamięci masowej nigdy nie są usuwane przez -v. Bind mount wskazuje ścieżkę na hoście, więc Docker tylko go odmontowuje, a pliki pozostają na swoim miejscu. Wolumen oznaczony jako external: true jest zadeklarowany jako należący do czegoś spoza tego projektu, dlatego Compose nigdy go nie usuwa. Nazwany wolumen usunięty z pliku Compose przed wykonaniem down -v nie jest już zadeklarowany, więc Compose nie wie, że należy go usunąć, i pozostawia go jako osierocony wolumen przez docker volume prune.
Ten ostatni przypadek często występuje podczas refaktoryzacji. Po usunięciu usługi i jej wolumenu z pliku wykonanie down -v nie usuwa wolumenu, ponieważ plik już o nim nie wspomina. Należy wykonać down -v przed edycją pliku, a nie po niej.
Kiedy rzeczywiście potrzebne jest --force-recreate
docker compose up -d nie przebudowuje wszystkiego przy każdym uruchomieniu. Compose zapisuje skrót rozwiązanej konfiguracji każdej usługi w kontenerze jako etykietę. Jeśli skrót i identyfikator obrazu są zgodne, kontener pozostaje bez zmian, a wynikiem jest Container voltest-db-1 Running zamiast Recreated. Zwykle jest to pożądane zachowanie, ponieważ dzięki temu wielokrotne uruchamianie up -d jest bezpieczne.
Dlatego niektóre zmiany pozornie niczego nie powodują. Compose oblicza skrót na podstawie rozwiązanej definicji usługi, a nie zawartości plików, do których ta definicja się odwołuje. Edycja pliku konfiguracyjnego zamontowanego w kontenerze i odczytywanego tylko podczas uruchamiania nie spowoduje ponownego utworzenia kontenera, ponieważ ścieżka montowania się nie zmieniła. Usługa nadal działa z wartościami odczytanymi podczas uruchamiania.
docker compose up -d --force-recreateZatrzymuje i usuwa każdy kontener, a następnie tworzy nowy na podstawie tej samej definicji. Należy użyć tej opcji po edycji zamontowanego pliku konfiguracyjnego oraz wtedy, gdy stan kontenera zmienił się w sposób, którego nie można wyjaśnić. Woluminy pozostają bez zmian, dlatego baza danych przetrwa wymuszone ponowne utworzenie. Aby użyć nowszego obrazu oznaczonego tym samym tagiem, trzeba dodatkowo wykonać pobieranie obrazu.
docker compose pull
docker compose up -dpull pobiera identyfikator nowego obrazu, a następnie up -d wykrywa, że identyfikator obrazu różni się od identyfikatora używanego przez działający kontener, i samodzielnie tworzy kontener ponownie. Dodanie --force-recreate bez pull powoduje utworzenie nowego kontenera na podstawie tego samego, starego obrazu. Dlatego często pojawia się uwaga: „Wymusiłem ponowne utworzenie, a nadal jest to stara wersja”.
docker compose restart nie wykonuje żadnej z tych czynności. Uruchamia ponownie istniejące kontenery i w ogóle nie odczytuje ponownie pliku Compose, dlatego zmieniona zmienna środowiskowa ani zmienione mapowanie portów nie zostaną zastosowane. Po edycji pliku należy użyć up -d.
Model, którego należy się trzymać
Kontenery można zastępować. Kontener to proces oraz cienka zapisywalna warstwa, a Compose może utworzyć identyczny kontener na podstawie pliku w około sekundę. Wolumenów nie można zastępować, ponieważ zawierają jedyną kopię stanu, której nie można odtworzyć na podstawie żadnego pliku w repozytorium.
Każde polecenie Compose odpowiada temu podziałowi. stop i start zachowują kontener. down i up zastępują kontener, zachowując wolumen. down -v to jedyne rutynowe polecenie usuwające stan, dlatego wymaga jawnego przełącznika. Przed użyciem go w rzeczywistym środowisku należy potwierdzić, że istnieje kopia zapasowa, z której przynajmniej raz wykonano odtworzenie.
Ta sama zasada dotyczy sekretów. Hasło ustawione za pomocą POSTGRES_PASSWORD jest odczytywane tylko podczas pierwszej inicjalizacji bazy danych, dlatego zmiana go w pliku środowiskowym i uruchomienie up -d powoduje password authentication failed for user "postgres". Kontener jest nowy, a wolumen pozostaje stary i nadal zawiera stare hasło. Jak Compose rozwiązuje pliki środowiskowe i sekrety wyjaśnia, która warstwa ma pierwszeństwo, gdy ta sama zmienna zostanie ustawiona dwukrotnie.
Tryby awarii i wyświetlane komunikaty
no configuration file provided: not found oznacza, że Compose działa w katalogu, w którym nie ma pliku compose.yaml ani docker-compose.yml. Należy przekazać -f z pełną ścieżką.
network voltest_default has active endpoints w down oznacza, że kontener spoza tego projektu jest podłączony do sieci projektu. Zwykle został uruchomiony ręcznie za pomocą docker run --network. Należy usunąć ten kontener, a następnie ponownie uruchomić down.
Found orphan containers ([voltest-old-1]) for this project pojawia się po zmianie nazwy lub usunięciu usługi. Stary kontener nadal ma etykietę projektu. docker compose down --remove-orphans usuwa takie kontenery. Polecenie można bezpiecznie wykonać dla działającego stosu.
Error response from daemon: remove voltest_pgdata: volume is in use podczas ręcznego wykonania docker volume rm oznacza, że któryś kontener nadal odwołuje się do woluminu, w tym kontener zatrzymany. Najpierw należy uruchomić docker compose down, a następnie usunąć wolumin albo użyć po prostu down -v. W większym projekcie wielousługowy stos Compose pokazuje, ile woluminów może zgromadzić jeden projekt.
FAQ
Czy docker compose down usuwa moją bazę danych?
Nie, jeśli baza danych znajduje się w nazwanym wolumenie lub w montowaniu bind mount. down usuwa kontenery i sieć projektu, a wolumen pozostaje na dysku wraz z niezmienionymi danymi. Następne docker compose up -d podłącza nowy kontener do tego samego wolumenu, więc dane są nadal dostępne. Tylko docker compose down -v usuwa nazwane wolumeny i tylko te zadeklarowane w sekcji volumes pliku Compose.
Jaka jest różnica między stop a down w przypadku kontenera, który ma zostać ponownie uruchomiony?
stop zachowuje kontener, dlatego docker compose start przywraca ten sam kontener z tą samą warstwą zapisywalną. Wszystko, co zainstalowano lub zmieniono ręcznie wewnątrz kontenera, nadal pozostaje dostępne. down usuwa kontener, dlatego następne up -d tworzy nowy kontener na podstawie obrazu, a ręcznie wprowadzone zmiany zostają utracone. Podczas debugowania należy używać stop.
Jak usunąć wszystko, co utworzył projekt Compose?
docker compose down -v --rmi all --remove-orphans usuwa kontenery, sieć projektu, nazwane wolumeny zadeklarowane w pliku, obrazy używane przez usługi oraz każdy kontener nadal oznaczony etykietą z nazwą projektu. Nie wpływa na montowania bind mount ani na wolumeny oznaczone jako external: true. Przed uruchomieniem należy sprawdzić za pomocą docker volume ls, które dane zostaną usunięte.
Dlaczego kontener ignoruje zmianę wprowadzoną w zamontowanym pliku konfiguracyjnym?
Compose decyduje o ponownym utworzeniu kontenera na podstawie porównania skrótu obliczonego z rozwiązanej definicji usługi. Ten skrót nie obejmuje zawartości zamontowanego pliku. Ścieżka się nie zmieniła, dlatego Compose pozostawia uruchomiony kontener z wartościami odczytanymi podczas uruchamiania. Należy uruchomić docker compose up -d --force-recreate, aby utworzyć nowy kontener, który ponownie odczyta plik.
Dlaczego nowa wartość POSTGRES_PASSWORD nie działa po jej zmianie?
Obraz Postgres odczytuje POSTGRES_PASSWORD tylko podczas inicjalizacji pustego katalogu danych. Wolumen zawiera już zainicjalizowany klaster, dlatego zmienna jest ignorowana i nadal obowiązuje stare hasło. Zostanie wyświetlony komunikat password authentication failed for user "postgres". Hasło należy zmienić za pomocą ALTER USER wewnątrz uruchomionej bazy danych albo zaakceptować utratę danych i rozpocząć od nowa za pomocą docker compose down -v.