Kontener można usunąć i odtworzyć w minutę. Problem zaczyna się wtedy, gdy razem z kontenerem znika baza danych, pliki użytkowników albo konfiguracja aplikacji. Przy Docker Compose trzeba jasno wiedzieć, co jest tylko obrazem, co jest kontenerem, a co jest danymi, które trzeba backupować.
Docker w dokumentacji podkreśla, że wolumeny są wygodne do backupu, odtwarzania i migracji. To prawda, ale sam fakt użycia wolumenu jeszcze nie oznacza, że backup istnieje. Wolumen tylko oddziela dane od cyklu życia kontenera. Kopię trzeba nadal zaplanować, wykonać i przetestować.
Poniżej praktyczny scenariusz dla administratora, który ma prosty stack w Docker Compose: aplikację, bazę danych i kilka wolumenów.
1. Najpierw sprawdź, gdzie są dane
Zacznij od katalogu z projektem:
cd /opt/aplikacja
docker compose ps
docker compose config
W pliku compose.yaml szukaj sekcji volumes. Przykład:
services:
app:
image: example/app:latest
volumes:
- app_data:/var/www/html/storage
db:
image: postgres:16
volumes:
- db_data:/var/lib/postgresql/data
volumes:
app_data:
db_data:
W tym przykładzie dane są w dwóch nazwanych wolumenach: app_data i db_data. Kontenery możesz odtworzyć z obrazu, ale zawartość tych wolumenów jest już Twoją odpowiedzialnością.
Lista wolumenów:
docker volume ls
docker volume inspect app_data
docker volume inspect db_data
Uwaga: przy Compose rzeczywista nazwa wolumenu często dostaje prefiks projektu, np. aplikacja_db_data. Dlatego zawsze sprawdzaj docker volume ls, a nie zakładaj nazwy z pamięci.
2. Backup wolumenu przez kontener techniczny
Docker pokazuje w dokumentacji podejście z uruchomieniem osobnego kontenera, który montuje wolumen i zapisuje archiwum do katalogu na hoście. W praktyce wygląda to tak:
mkdir -p /backup/docker/aplikacja
docker run --rm \
-v aplikacja_app_data:/data:ro \
-v /backup/docker/aplikacja:/backup \
alpine \
tar -czf /backup/app_data-$(date +%F-%H%M).tar.gz -C /data .
Kilka ważnych szczegółów:
- wolumen montuję jako
:ro, czyli tylko do odczytu, - archiwum zapisuję poza Dockerem, w
/backup/docker/aplikacja, - w archiwum nie zapisuję całej ścieżki
/var/lib/docker/..., tylko zawartość wolumenu, - nazwa pliku zawiera datę i godzinę.
To jest dobre dla plików aplikacji, uploadów, konfiguracji i danych, które mogą być spójnie odczytane jako pliki.
3. Baza danych: nie zawsze wystarczy tar wolumenu
Jeżeli wolumen zawiera bazę danych, sam tar z działającego kontenera może nie dać spójnej kopii. Baza w tym czasie zapisuje dane, ma cache, transakcje i pliki pomocnicze. Dla PostgreSQL albo MySQL bezpieczniej robić logiczny dump.
Przykład PostgreSQL:
mkdir -p /backup/docker/aplikacja
docker compose exec -T db \
pg_dump -U postgres nazwa_bazy \
> /backup/docker/aplikacja/postgres-$(date +%F-%H%M).sql
Przykład MySQL/MariaDB:
docker compose exec -T db \
mysqldump -u root -p nazwa_bazy \
> /backup/docker/aplikacja/mysql-$(date +%F-%H%M).sql
Jeżeli baza ma dużo danych, rozważ kompresję:
docker compose exec -T db \
pg_dump -U postgres nazwa_bazy \
| gzip > /backup/docker/aplikacja/postgres-$(date +%F-%H%M).sql.gz
Najlepszy wariant dla prostego stacka: dump bazy plus backup wolumenów z plikami aplikacji.
4. Restore trzeba przetestować
Backup bez testu odtworzenia to tylko plik, który może działać albo nie. Test nie musi od razu dotyczyć produkcji. Możesz odtworzyć stack w katalogu testowym albo na osobnej maszynie.
Odtworzenie wolumenu z archiwum:
docker volume create restore_app_data
docker run --rm \
-v restore_app_data:/data \
-v /backup/docker/aplikacja:/backup \
alpine \
tar -xzf /backup/app_data-2026-06-20-1000.tar.gz -C /data
Potem podstawiasz wolumen w testowym compose.yaml i uruchamiasz usługę:
docker compose up -d
docker compose logs -f
Przy bazie danych odtwarzaj dump do pustej bazy. Dla PostgreSQL przykładowo:
cat /backup/docker/aplikacja/postgres-2026-06-20-1000.sql \
| docker compose exec -T db psql -U postgres nazwa_bazy
Po odtworzeniu sprawdź aplikację normalnie: logowanie, lista rekordów, upload plików, działanie zadań w tle.
5. Nie backupuj tylko tego, co łatwo znaleźć
W stacku Compose często są też rzeczy poza wolumenami:
- plik
compose.yaml, - pliki
.env, - konfiguracje reverse proxy,
- certyfikaty,
- katalogi bind mount,
- skrypty startowe,
- zadania cron albo systemd timers,
- konfiguracja firewalla,
- dokumentacja, jak uruchomić stack po awarii.
Minimum, które warto trzymać w kopii:
tar -czf /backup/docker/aplikacja/compose-config-$(date +%F-%H%M).tar.gz \
compose.yaml .env nginx/ scripts/
Jeżeli w .env są hasła, pilnuj uprawnień do backupu. Docker w dokumentacji przypomina, żeby nie używać zmiennych środowiskowych do przekazywania wrażliwych danych, jeżeli można użyć secrets. W Compose sekrety trafiają do kontenera jako pliki w /run/secrets/..., a dostęp można ograniczać per usługa.
6. Prosty skrypt backupu
Przykład prostego skryptu dla aplikacji z wolumenem plików i bazą PostgreSQL:
#!/usr/bin/env bash
set -euo pipefail
PROJECT_DIR="/opt/aplikacja"
BACKUP_DIR="/backup/docker/aplikacja"
DATE="$(date +%F-%H%M)"
mkdir -p "$BACKUP_DIR"
cd "$PROJECT_DIR"
docker compose exec -T db \
pg_dump -U postgres nazwa_bazy \
| gzip > "$BACKUP_DIR/postgres-$DATE.sql.gz"
docker run --rm \
-v aplikacja_app_data:/data:ro \
-v "$BACKUP_DIR":/backup \
alpine \
tar -czf "/backup/app_data-$DATE.tar.gz" -C /data .
tar -czf "$BACKUP_DIR/compose-config-$DATE.tar.gz" compose.yaml .env
find "$BACKUP_DIR" -type f -mtime +14 -delete
Nadaj uprawnienia:
chmod 700 backup-docker-aplikacja.sh
I uruchamiaj z crona albo przez systemd timer. Przy ważnych systemach lepiej użyć systemd timer, bo łatwiej sprawdzić logi i status wykonania.
7. Na co uważać
Najczęstsze błędy:
- backupowany jest kontener, ale nie wolumen z danymi,
- robiony jest
tardziałającej bazy zamiast dumpa, - backup zostaje na tym samym dysku co Docker,
- nikt nie testuje odtworzenia,
- skrypt backupu usuwa stare kopie bez sprawdzenia, czy nowa kopia się udała,
- plik
.envz hasłami trafia do kopii dostępnej dla zbyt wielu osób, - nazwa wolumenu w skrypcie nie zgadza się z rzeczywistą nazwą Compose,
- po migracji na inny serwer zapomniano o reverse proxy, DNS albo certyfikatach.
Szczególnie groźne jest przekonanie, że docker compose down niczego nie rusza. Samo down zwykle nie usuwa nazwanych wolumenów, ale down -v już tak. Na produkcji trzeba bardzo świadomie używać opcji, które kasują wolumeny.
8. Jak sprawdzić, czy backup ma sens
Po wykonaniu kopii sprawdź:
ls -lh /backup/docker/aplikacja
tar -tzf /backup/docker/aplikacja/app_data-YYYY-MM-DD-HHMM.tar.gz | head
gzip -t /backup/docker/aplikacja/postgres-YYYY-MM-DD-HHMM.sql.gz
Raz na jakiś czas zrób pełny test:
- Utwórz pustą maszynę albo katalog testowy.
- Skopiuj backup.
- Odtwórz wolumeny i bazę.
- Uruchom stack.
- Sprawdź aplikację z przeglądarki.
- Zapisz czas odtworzenia.
W firmie bardziej przydaje się informacja „odtworzenie trwa 35 minut i wymaga zmiany DNS” niż samo „backup jest”.
Podsumowanie
W Docker Compose najważniejsze dane zwykle siedzą w wolumenach, bazach danych i plikach konfiguracyjnych obok compose.yaml. Kontener można odtworzyć z obrazu, ale danych użytkowników i bazy nikt za nas nie odzyska.
Dobre minimum to: dump bazy, archiwum wolumenów, kopia konfiguracji Compose, kopia poza serwerem i regularny test restore. Dopiero wtedy można powiedzieć, że stack w Dockerze ma backup, a nie tylko katalog z przypadkowymi plikami.
Źródła
- Docker volumes: https://docs.docker.com/engine/storage/volumes/
- Docker Compose secrets: https://docs.docker.com/compose/how-tos/use-secrets/
- Docker Compose environment variables: https://docs.docker.com/compose/how-tos/environment-variables/set-environment-variables/