SSD Nodes Learn 🎉 VPS od $5.50/mies.
Przewodniki Matt ConnorAutor: Matt Connor · Zaktualizowano 2026-08-13

Baza danych w Docker czy na hoście: co wybrać?

Analiza wdrożeń PostgreSQL, MySQL i Redis w kontenerach. Dowiedz się, jak zarządzać wolumenami, aktualizacjami i kopiami zapasowymi, aby uniknąć błędów w środowisku produkcyjnym.

Czy baza danych powinna działać w Docker czy na hoście?

Bazę danych należy uruchamiać w Docker. W przypadku pojedynczego stosu aplikacji na jednym VPS, konteneryzowany PostgreSQL, MySQL, MongoDB lub Redis jest standardowym rozwiązaniem produkcyjnym, a dyskusje na ten temat zazwyczaj koncentrują się na niewłaściwych argumentach. Kontener to proces systemu Linux z nałożonymi przestrzeniami nazw (namespaces) i grupami kontrolnymi (cgroups), a nie maszyna wirtualna, więc między bazą danych a dyskiem nie występuje żaden hypervisor. Dzięki bind mount lub lokalnemu wolumenowi nazwanemu, operacje odczytu i zapisu trafiają bezpośrednio na system plików hosta, czyli ten sam, z którego korzystałaby instalacja pakietowa.

Rzeczywisty koszt ma charakter operacyjny. O tym, czy taka konfiguracja jest poprawna, czy stanie się źródłem problemów, decydują cztery kwestie: lokalizacja danych, właściciel katalogu, przebieg aktualizacji głównej wersji oraz fakt, czy kiedykolwiek przywracano kopię zapasową. Jeśli te elementy zostaną poprawnie skonfigurowane, kontener staje się jedynie szczegółem technicznym. W przeciwnym razie kontener będzie pierwszym elementem, który zostanie obarczony winą za awarię.

Decyzja ta wygląda identycznie dla każdej bazy danych na serwerze. Poniższe przykłady wykorzystują PostgreSQL, MySQL, MongoDB oraz Redis, a różnice specyficzne dla danego produktu zostały wskazane tam, gdzie mają znaczenie.

Co faktycznie zmienia kontener

Nie zmienia ścieżki przechowywania danych, o ile zamontowano wolumen. Używany jest ten sam kernel, ta sama pamięć podręczna stron (page cache) i ten sam system plików.

Istnieje jedna istotna pułapka wydajnościowa, występująca w przypadku braku montowania wolumenów. Bez wolumenu katalog danych trafia do warstwy zapisu kontenera, będącej systemem plików typu overlay nałożonym na obraz. Operacje zapisu w tym miejscu są wolniejsze, a cała warstwa jest usuwana wraz z usunięciem kontenera. To właśnie przyczyna sytuacji, w których baza danych okazuje się pusta po restarcie.

Co zmienia się faktycznie:

  • Cykl życia. docker compose down niszczy kontener. Wszystko, co nie znajdowało się w wolumenie, zostaje usunięte.
  • Wersja. Wersję określa tag obrazu. Wewnątrz kontenera z bazą danych nie ma żadnego apt upgrade, który przetrwałby kolejny docker compose pull.
  • Rozliczanie pamięci. Limit cgroup stanowi twardą barierę narzuconą przez kernel, o której baza danych nie posiada informacji.
  • Użytkownik. Proces działa jako numeryczny identyfikator użytkownika (UID) wewnątrz kontenera, który może nie posiadać żadnych uprawnień do plików na hoście.

Lokalizacja danych determinuje wszystko

Istnieją dwie dobre opcje oraz jeden powszechny błąd.

  • Wolumen nazwany: pgdata:/var/lib/postgresql/data. Docker tworzy katalog w /var/lib/docker/volumes/<project>_pgdata/_data, a punkt wejścia obrazu ustawia uprawnienia przy pierwszym uruchomieniu. Jest to domyślne rozwiązanie.
  • Montowanie typu bind mount: /srv/appname/pg:/var/lib/postgresql/data. Użytkownik wybiera ścieżkę, więc sam odpowiada za kwestię uprawnień.
  • Brak montowania. Patrz wyżej. Dane znajdują się wewnątrz kontenera.

Pełne zestawienie wad i zalet to osobny temat, a artykuł bind mounts against named volumes omawia go szczegółowo. W przypadku bazy danych skrócona wersja brzmi: należy używać wolumenu nazwanego, chyba że istnieje konkretny powód, aby znać ścieżkę na hoście. Jeśli konieczne jest użycie bind mount, należy umieścić go w stabilnym miejscu, takim jak /srv/appname/pg, zamiast wewnątrz katalogu projektu, gdzie może uzyskać do niego dostęp git clean.

Jedno twarde ograniczenie: nie należy umieszczać katalogu danych bazy danych na systemie NFS (network file system) ani na żadnym montowaniu sieciowym, którego mechanizm blokowania i zachowanie fsync nie zostały przetestowane. Bazy danych zakładają, że pomyślny fsync oznacza zapis bajtów na trwałym nośniku. Gdy to założenie jest błędne, dochodzi do uszkodzenia danych, które ujawnia się dopiero po kilku tygodniach.

Przypisanie nazwy wolumenu przed jego utratą

Compose nadaje wolumenowi nazwę <project>_<volume>, a nazwa projektu domyślnie pochodzi od nazwy katalogu. Tożsamość wolumenu zależy zatem od nazwy katalogu, co jest parametrem często zmienianym bez głębszego zastanowienia.

Przeniesienie /srv/app do /srv/app-old lub zmiana nazwy klucza pgdata w pliku compose spowoduje, że kolejne polecenie docker compose up -d utworzy zupełnie nowy, pusty wolumen. Postgres zainicjuje w nim świeży klaster. Kontener będzie w stanie healthy, aplikacja wystartuje, a wszystkie tabele znikną. Dobrą wiadomością jest to, że stary wolumen nadal znajduje się na dysku pod starą nazwą.

docker volume ls
docker volume inspect app_pgdata

Przypisz nazwy na sztywno, aby zapobiec takiej sytuacji. Zdefiniuj jawnie nazwę projektu oraz nazwę wolumenu:

name: myapp

services:
  db:
    image: postgres:17
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:
    name: myapp_pgdata

Jeśli dane znajdują się w porzuconym wolumenie, skopiuj je po zatrzymaniu bazy danych:

docker compose stop db
docker run --rm -v app_pgdata:/from -v myapp_pgdata:/to alpine sh -c 'cp -a /from/. /to/'
docker compose start db

Kopiowanie w trakcie działania bazy danych prowadzi do powstania niespójnej kopii plików, które były w tym czasie zapisywane. Najpierw zatrzymaj usługę.

Kto jest właścicielem katalogu danych

Oficjalne obrazy Postgres, MySQL oraz MongoDB uruchamiają serwer jako użytkownik bez uprawnień, zazwyczaj o identyfikatorze 999. Gdy kontener startuje jako root, punkt wejścia (entrypoint) zmienia właściciela katalogu danych na tego użytkownika, a następnie porzuca uprawnienia. Dlatego puste dowiązanie (bind mount) zazwyczaj działa przy pierwszej próbie.

Mechanizm ten przestaje działać w momencie ustawienia user: w pliku compose, ponieważ punkt wejścia nie posiada wówczas uprawnień niezbędnych do wprowadzenia zmian. Postgres informuje o tym bezpośrednio:

initdb: error: could not change permissions of directory "/var/lib/postgresql/data": Operation not permitted

Katalog danych istniejący z niewłaściwymi uprawnieniami generuje inny komunikat. Warto go rozpoznać, ponieważ rozwiązaniem jest chmod, a nie chown:

FATAL:  data directory "/var/lib/postgresql/data" has invalid permissions
DETAIL:  Permissions should be u=rwx (0700) or u=rwx,g=rx (0750).

MongoDB na dowiązaniu należącym do roota kończy działanie błędem pliku blokady:

Unable to create/open the lock file: /data/db/mongod.lock (Permission denied). Ensure the user executing mongod is the owner of the lock file and has the appropriate permissions.

Rozwiązaniem jest zmiana właściciela katalogu na hoście na identyfikator numeryczny, a nie na nazwę użytkownika:

sudo chown -R 999:999 /srv/appname/pg
sudo chmod 700 /srv/appname/pg
ls -ldn /srv/appname/pg

ls -ldn wyświetla numery zamiast nazw i powinno wskazywać 999 999. Konto o nazwie postgres na hoście oraz konto o nazwie postgres wewnątrz obrazu nie są ze sobą powiązane: jądro systemu porównuje numery, a nazwy są sprawdzane niezależnie po każdej ze stron. w jaki sposób PUID i PGID mapują użytkowników hosta do kontenera szczegółowo opisuje ten proces mapowania. W przypadku Docker rootless lub remappingu przestrzeni nazw użytkownika (user namespace remapping) numery te ulegają zmianie, dlatego należy odczytać identyfikatory z uruchomionego kontenera, zamiast zakładać wartość 999.

Wolumeny nazwane (named volumes) eliminują ten problem przy pierwszym uruchomieniu, ponieważ Docker tworzy pusty katalog, a punkt wejścia przejmuje nad nim własność.

Aktualizacje: aktualizacja pakietu przy zmianie tagu obrazu

Na hoście polecenie apt upgrade pozwala na przejście do kolejnej wersji mniejszej. Dystrybucja nie dokona automatycznego przejścia na wyższą wersję główną bazy danych, a w przypadku decyzji o takiej aktualizacji, oba zestawy plików binarnych mogą być zainstalowane jednocześnie, co jest dokładnie tym, czego wymaga pg_upgrade.

W kontenerze tag jest wersją, więc aktualizacja polega na edycji jednej linii. Dzięki temu aktualizacje wersji mniejszych są trywialne, a aktualizacje wersji głównych stają się sformalizowaną procedurą.

Zmień postgres:16 na postgres:17, uruchom docker compose up -d, a kontener natychmiast zakończy działanie:

PostgreSQL Database directory appears to contain a database; Skipping initialization
FATAL:  database files are incompatible with server
DETAIL:  The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 17.

Nic nie ulega uszkodzeniu. Nowe pliki binarne odmawiają odczytu starego układu katalogu na dysku, który zmienia się pomiędzy wersjami głównymi. Przywróć tag postgres:16, a usługa uruchomi się ponownie. Taki mechanizm wycofywania zmian jest jedyną rzeczywistą zaletą aktualizacji w kontenerach.

Wspieraną ścieżką jest zrzut i przywrócenie danych. PostgreSQL preferuje, aby zrzut był wykonany przez nowszego klienta, dlatego należy uruchomić go z poziomu nowego obrazu względem wciąż działającego starego serwera w sieci compose:

docker run --rm --network myapp_default -e PGPASSWORD="$POSTGRES_PASSWORD" \
  postgres:17 pg_dumpall -h db -U postgres > /srv/backups/all.sql
ls -lh /srv/backups/all.sql
tail -n 2 /srv/backups/all.sql

Plik powinien mieć rozmiar co najmniej kilkudziesięciu kilobajtów i kończyć się linią o treści PostgreSQL database cluster dump complete. Plik o rozmiarze kilkuset bajtów oznacza, że zrzut nie powiódł się i usunięcie wolumenu byłoby bezcelowe. Dopiero po weryfikacji wykonaj:

docker compose down
docker volume rm myapp_pgdata
# edit the compose file: image: postgres:17
docker compose up -d db
docker compose exec -T db psql -U postgres -f /dev/stdin < /srv/backups/all.sql

Inne silniki działają inaczej:

  • MySQL 8 aktualizuje własny słownik danych przy starcie, więc zmiana tagu wersji mniejszej zazwyczaj wymaga jedynie restartu. Przed przejściem między seriami wydań przeczytaj informacje o wersji i w każdym przypadku wykonaj wcześniej zrzut danych.
  • MariaDB wymaga uruchomienia mariadb-upgrade po podniesieniu serwera do nowej wersji.
  • MongoDB musi być aktualizowane o jedną wersję główną na raz, a po każdym kroku należy ustawić wersję kompatybilności funkcji przed przejściem dalej. Pominięcie wersji spowoduje, że mongod odmówi startu i zapisze w logach linię UPGRADE PROBLEM wskazującą na featureCompatibilityVersion. Od wersji MongoDB 7.0 polecenie wymaga jawnej flagi potwierdzenia: db.adminCommand({ setFeatureCompatibilityVersion: "8.0", confirm: true }).
  • Redis bez problemu wczytuje starsze pliki migawek, ale nie nowsze, więc aktualizacja to restart, a przy próbie przywrócenia starszej wersji wczytanie danych może się nie udać.

Ogólna zasada: kontener ułatwia wycofanie zmian, ale nie ułatwia samej aktualizacji.

Dlaczego mój kontener z bazą danych kończy działanie z kodem 137?

Dzieje się tak, ponieważ mechanizm OOM (Out of Memory) jądra systemu przerwał jego pracę. Kod 137 to suma 128 oraz sygnału 9.

docker compose ps
docker inspect myapp-db-1 | grep -i oomkilled
journalctl -k | tail -n 20

docker compose ps wyświetla Exited (137), linia w inspect zawiera "OOMKilled": true, a dziennik jądra zawiera pasujący wpis:

Memory cgroup out of memory: Killed process 4711 (postgres) total-vm:2170416kB

Mechanizm ten często zaskakuje użytkowników. PostgreSQL oraz MySQL określają rozmiar swoich buforów na podstawie całkowitej pamięci zgłaszanej przez hosta. Limit cgroup nie zmienia tej wartości dla aplikacji. Na hoście z 16 GB pamięci i limitem 2 GB dla kontenera, baza danych planuje pracę tak, jakby miała do dyspozycji 16 GB. W rezultacie cgroup przerywa proces na długo przed wystąpieniem rzeczywistego braku pamięci na hoście. Sam limit pamięci zatem nie wystarcza. Należy jawnie wskazać bazie danych dostępną ilość zasobów:

  • PostgreSQL: ustaw shared_buffers i zwróć uwagę na work_mem. work_mem jest przydzielane dla każdej operacji sortowania w ramach połączenia, więc zbyt wysoka wartość pomnożona przez pięćdziesiąt połączeń jest najczęstszą przyczyną wyłączania się kontenera pod obciążeniem, a nie podczas startu.
  • MySQL oraz MariaDB: ustaw innodb_buffer_pool_size, którego domyślna wartość to 128M. Wyłącz innodb_dedicated_server w kontenerze, ponieważ jego zadaniem jest automatyczne dopasowanie rozmiaru do wykrytej pamięci maszyny.
  • MongoDB: ustaw rozmiar pamięci podręcznej WiredTiger jawnie, zamiast pozwalać na szacowanie na podstawie pamięci hosta.
  • Redis: maxmemory domyślnie jest nieograniczone, więc Redis rośnie, dopóki cgroup go nie zatrzyma. Ustaw maxmemory na wartość bezpiecznie poniżej limitu kontenera i wybierz odpowiednią maxmemory-policy.

Postgres również raportuje to zdarzenie po swojej stronie; w dzienniku znajdziesz następującą parę linii:

LOG:  server process (PID 123) was terminated by signal 9: Killed
LOG:  terminating any other active sessions due to crash of another server process

Przerwanie jednego procesu backendu wymusza restart wszystkich pozostałych, ponieważ pamięć współdzielona może stać się niespójna. Dla aplikacji oznacza to gwałtowny wzrost liczby połączeń, a nie ciche zdarzenie. ustawianie limitów pamięci w Docker Compose opisuje składnię oraz różnicę między mem_limit a formą deploy.resources.

Problem ten nie znika na hoście, lecz zostaje przeniesiony. Bez cgroup baza danych rywalizuje o zasoby ze wszystkimi innymi procesami, a mechanizm OOM jądra wybiera ofiarę na podstawie punktacji, co może doprowadzić do przerwania pracy sshd. Limit, który przewidywalnie wyłącza bazę danych, jest łatwiejszy w obsłudze niż OOM hosta, który może zablokować dostęp do systemu.

Kopie zapasowe: zrzut wewnątrz, kopia na zewnątrz

Nie należy tworzyć kopii zapasowej działającej bazy danych poprzez kopiowanie jej katalogu z danymi. Kopia na poziomie plików wykonana w trakcie zapisu przez serwer jest kopią niespójną, co ujawnia się dopiero w momencie przywracania danych.

Istnieją dwie poprawne metody: wykonanie zrzutu za pomocą wbudowanego narzędzia bazy danych podczas jej pracy i zabezpieczenie tego zrzutu lub zatrzymanie kontenera i wykonanie kopii wolumenu w trybie "na zimno".

docker compose exec -T db pg_dump -U postgres -Fc appdb > /srv/backups/appdb.dump
docker compose exec -T db mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" --single-transaction --all-databases > /srv/backups/mysql.sql
docker compose exec -T db mongodump --archive --gzip --db appdb > /srv/backups/appdb.archive.gz
docker compose exec -T redis redis-cli BGSAVE

Flaga -T jest kluczowa. Bez niej docker compose exec może podpiąć terminal do polecenia, co spowoduje dodanie znaków powrotu karetki do strumienia wyjściowego. Zrzut tekstowy przywróci się wtedy z błędami, a zrzut binarny będzie po prostu uszkodzony. Proces ten kończy się niepowodzeniem w sposób cichy podczas tworzenia kopii, a w sposób głośny miesiąc później.

Opcja --single-transaction zapewnia mysqldump spójną migawkę tabel InnoDB bez blokowania całego serwera.

Powyższe polecenia tworzą pojedyncze pliki. Nie stanowią one systemu kopii zapasowych: brakuje w nich retencji, kopiowania poza serwer oraz weryfikacji. Katalog ze zrzutami należy przekazać narzędziu, które realizuje wszystkie trzy funkcje, co opisano w restic backups from a VPS. Należy tworzyć kopie zapasowe /srv/backups, a nie /var/lib/docker/volumes.

Następnie należy przeprowadzić procedurę przywracania, ponieważ kopia, której nigdy nie przywrócono, nie jest kopią zapasową:

docker compose exec -T db createdb -U postgres restore_test
docker compose exec -T db pg_restore -U postgres -d restore_test < /srv/backups/appdb.dump
docker compose exec -T db psql -U postgres -d restore_test -c '\dt'

Polecenie \dt powinno wyświetlić tabele aplikacji. Pusty wynik lub Did not find any relations. oznacza, że zrzut nie zawiera oczekiwanych danych. Po zakończeniu pracy należy usunąć restore_test.

Polecenie usuwające wszystko

docker compose down -v.

Zwykłe down usuwa kontenery oraz sieć. Polecenie -v usuwa również każdy wolumen nazwany zadeklarowany w pliku compose, a także wszystkie wolumeny anonimowe podpięte do tych kontenerów. Operacja nie wyświetla monitu o potwierdzenie i nie można jej cofnąć. Jest to najczęstsza przyczyna utraty danych w bazach danych hostowanych samodzielnie; zazwyczaj dochodzi do tego podczas rozwiązywania niezwiązanych z tym problemów, gdy użytkownik wykonuje polecenie zasugerowane na forum.

Cztery zasady ograniczają zakres potencjalnych szkód:

  • Deklaruj wolumeny baz danych jako external: true. Compose nie usuwa wolumenów, którymi nie zarządza, więc -v nie będzie w stanie ich usunąć. Wolumen tworzy się jednorazowo za pomocą docker volume create myapp_pgdata.
  • Używaj docker compose stop oraz docker compose start do rutynowych restartów. down kontra stop w Compose wyjaśnia, co usuwa każde z tych poleceń.
  • Przechowuj zrzuty baz danych w ścieżce na hoście, poza wolumenami zarządzanymi przez compose.
  • Nigdy nie wklejaj -v z odpowiedzi na forum do stosu zawierającego ważne dane.

Nie publikuj portu bazy danych

Poniższa linia udostępnia bazę danych w publicznym Internecie:

    ports:
      - "5432:5432"

Powoduje ona powiązanie z każdym interfejsem sieciowym. Docker publikuje port poprzez nadpisanie miejsca docelowego pakietu, zanim reguły wejściowe firewalla zdążą go przetworzyć. Reguły ufw znajdują się w łańcuchu input, dlatego ufw deny 5432 nie przynosi żadnego efektu. dlaczego publikowane porty Dockera omijają ufw przedstawia sposób przechodzenia pakietów przez łańcuchy.

Aplikacja w tym samym projekcie compose uzyskuje dostęp do bazy danych za pomocą nazwy usługi w sieci compose, więc nie wymaga publikowania portu. Usuń ten blok. Jeśli potrzebujesz dostępu dla klienta na hoście, powiąż usługę wyłącznie z interfejsem loopback:

    ports:
      - "127.0.0.1:5432:5432"

Sprawdź, co faktycznie nasłuchuje na portach:

sudo ss -ltnp | grep 5432

127.0.0.1:5432 to pożądany stan. 0.0.0.0:5432 oznacza, że każdy może podjąć próbę odgadnięcia hasła.

Co i gdzie uruchamiać

Jedna aplikacja na jednym VPS. Kontener. Nazwany wolumen z przypisaną nazwą, bez wystawionego portu, z limitem pamięci dopasowanym do ustawień bazy danych oraz nocnym zrzutem do ścieżki na hoście, z której dane pobiera restic. Zacznij od czystej instalacji Docker na VPS i utrzymuj stos w jednym pliku compose, który zatwierdzasz w repozytorium. Zysk jest wymierny: wersja bazy danych staje się możliwą do przejrzenia linią w git.

Host uruchamiający kilka usług. Kontenery, jedna baza danych na aplikację, a nie jeden współdzielony serwer dla wszystkich. Współdzielony serwer wiąże każdą aplikację z jednym harmonogramem aktualizacji, a jedno zapytanie powodujące przeciążenie staje się awarią dla wszystkich. Przypisz każdemu kontenerowi własny limit pamięci, aby błędne zapytanie było ograniczone do aplikacji, która je wygenerowała. Kilka małych instancji Postgres kosztuje nieco więcej miejsca na dysku, ale wymaga znacznie mniej koordynacji.

Baza danych jest produktem. Uruchom ją na hoście z repozytorium pakietów dostawcy lub skorzystaj z płatnej usługi zarządzanej. pg_upgrade wymaga jednoczesnej instalacji obu głównych wersji plików binarnych, co zapewniają pakiety, a czego nie oferuje obraz z jedną wersją. Replikacja oraz odzyskiwanie do punktu w czasie (PITR) z archiwizacją WAL (write ahead log) są łatwiejsze, gdy baza danych posiada pełną kontrolę nad maszyną i jej dyskami. Wybierz przewidywalną ścieżkę dla systemu, który będzie wysyłał powiadomienia o awarii o 03:00.

Aplikacja jest mała. Rozważ rezygnację z serwerowej bazy danych. Aplikacja internetowa z jednym zapisującym procesem na jednym VPS często lepiej działa z SQLite w środowisku produkcyjnym na VPS, gdzie kopia zapasowa to jeden plik, a ścieżka aktualizacji ogranicza się do wersji biblioteki.

FAQ

Czy uruchamianie produkcyjnej bazy danych w Docker jest bezpieczne?

Tak, w przypadku stosu aplikacji działającego na pojedynczym serwerze. Kontener to proces systemu Linux ograniczony przez przestrzenie nazw (namespaces) i cgroups, więc przy zamontowanym wolumenie baza danych zapisuje dane w tym samym systemie plików hosta, co w przypadku instalacji z pakietu. Ryzyko ma charakter operacyjny, a nie wydajnościowy: wolumen o nieprzypisanej nazwie, bind mount z błędnym właścicielem (user id), nieprzetestowana procedura przywracania danych oraz docker compose down -v. Wyeliminowanie tych czterech czynników sprawia, że kontener jest bezpieczny. Przejdź na instalację bezpośrednio na hoście, gdy baza danych stanowi główne obciążenie i wymagane są pg_upgrade, replikacja lub odtwarzanie do punktu w czasie (point in time recovery).

Czy do danych bazy danych użyć bind mount czy nazwanego wolumenu?

Używaj nazwanego wolumenu, chyba że istnieje konkretny powód, dla którego musisz znać ścieżkę na hoście. Docker tworzy katalog, a punkt wejścia (entrypoint) obrazu ustawia uprawnienia przy pierwszym uruchomieniu, dzięki czemu problem z dostępem nie występuje. Przypisz wolumen za pomocą jawnego name: lub oznacz go jako external: true, w przeciwnym razie zmiana nazwy katalogu projektu spowoduje automatyczne utworzenie nowego, pustego wolumenu i pustej bazy danych. Bind mount jest dopuszczalny, jeśli zmienisz właściciela katalogu na hoście (chown) na numeryczny identyfikator użytkownika, z którym działa obraz (dla oficjalnych obrazów Postgres, MySQL i MongoDB jest to 999). Zweryfikuj to za pomocą ls -ldn, ponieważ ls -l wyświetla nazwę użytkownika z hosta dla tego numeru, a ta nazwa nie ma znaczenia wewnątrz kontenera.

Co usuwa docker compose down -v?

Polecenie to usuwa kontenery i sieć, podobnie jak zwykłe down, a flaga -v dodatkowo usuwa każdy nazwany wolumen zadeklarowany w pliku compose oraz każdy anonimowy wolumen podpięty do tych kontenerów. Dotyczy to również bazy danych. Nie ma monitu z potwierdzeniem ani możliwości odzyskania danych. Wolumeny oznaczone jako external: true nie są usuwane, co jest głównym powodem oznaczania wolumenu bazy danych jako zewnętrzny. Do rutynowego restartu używaj docker compose stop oraz docker compose start.

Jak zaktualizować PostgreSQL do nowej wersji głównej w Docker?

Wykonaj zrzut (dump) i przywracanie. Zmiana postgres:16 na postgres:17 i restart spowoduje FATAL: database files are incompatible with server z komunikatem DETAIL wskazującym obie wersje, ponieważ nowe pliki binarne nie odczytają układu katalogów starej wersji. Nic nie ulega uszkodzeniu: przywrócenie starego tagu pozwala na uruchomienie bazy. Wykonaj pg_dumpall, używając klienta nowej wersji przeciwko działającemu staremu kontenerowi, upewnij się, że plik kończy się ciągiem PostgreSQL database cluster dump complete, a następnie uruchom nowy tag na pustym wolumenie i wczytaj zrzut. Mniejsze aktualizacje w ramach jednej wersji głównej wymagają jedynie pobrania obrazu (pull) i restartu.

Dlaczego mój kontener z bazą danych kończy działanie z kodem 137?

137 to 128 plus sygnał 9, co oznacza, że proces został natychmiastowo zabity. Uruchom docker inspect <container> | grep -i oomkilled; wartość true oznacza, że kontener osiągnął limit pamięci cgroup. Typową przyczyną jest to, że PostgreSQL i MySQL odczytują całkowitą pamięć hosta i nie widzą limitu kontenera, więc planują wykorzystanie 16 GB, działając wewnątrz 2 GB. Ustaw shared_buffers i work_mem lub innodb_buffer_pool_size, aby dopasować parametry do limitu przydzielonego kontenerowi. Sprawdź journalctl -k pod kątem pasującej linii Memory cgroup out of memory, aby potwierdzić, który proces został wybrany przez jądro systemu.