Servery a DevOps

Docker volumes a zálohy: jak nepřijít o data v kontejnerech

Rozdíl mezi volume a bind mountem, kde Docker data fyzicky ukládá, záloha a obnova volume přes tar, konzistentní dump PostgreSQL a MySQL a automatizace cronem.

12. 10. 2026 · 4 min čtení

Kontejnery jsou dočasné – smažete je a vytvoříte znovu. Data ale dočasná být nesmí. Docker na to má volumes a bind mounty. A protože volume není záloha, ukážeme si také, jak data spolehlivě zálohovat a obnovit.

Tři způsoby ukládání dat

Typ Zápis Kde data jsou Kdy použít
Pojmenovaný volume -v pgdata:/var/lib/postgresql/data spravuje Docker (/var/lib/docker/volumes/) databáze, data aplikací
Bind mount -v /srv/app/uploads:/app/uploads konkrétní složka hostitele konfigurace, nahrané soubory, vývoj
tmpfs --tmpfs /tmp v RAM dočasná data, nic se neukládá

Bez žádné z těchto možností data zmizí při smazání kontejneru.

Práce s volumes

docker volume ls
docker volume inspect pgdata
docker volume rm pgdata          # smaže data!
docker volume prune              # smaže nepoužívané volumes

inspect ukáže Mountpoint, typicky /var/lib/docker/volumes/pgdata/_data. Do této složky sice jde nahlédnout jako root, ale přímo do ní nesahejte za běhu kontejneru.

V Compose se volume jmenuje s prefixem projektu: volume pgdata v projektu shop bude shop_pgdata.

Pozor na prune

docker system prune ve výchozím stavu volumes nemaže. docker system prune --volumes a docker volume prune ano – smažou volumes nepřipojené k žádnému kontejneru. Pokud jste mezitím udělali docker compose down, databázový volume je „nepoužívaný“. Před prune vždy zkontrolujte docker volume ls.

Bind mount: práva k souborům

U bind mountů musí uživatel v kontejneru mít práva k souborům na hostiteli. Pokud kontejner běží jako UID 1000:

sudo chown -R 1000:1000 /srv/app/uploads

Konfiguraci připojujte jen pro čtení:

volumes:
  - ./nginx.conf:/etc/nginx/nginx.conf:ro

Záloha databáze: dump, ne kopie souborů

Kopírovat soubory běžící databáze je riskantní – můžete zachytit nekonzistentní stav. Pro databáze použijte jejich nástroj na export.

PostgreSQL:

docker compose exec -T db pg_dump -U app -Fc app > backup_$(date +%F).dump

Volba -T vypne pseudo-terminál, jinak by se výstup mohl poškodit. -Fc je komprimovaný vlastní formát pro pg_restore.

Obnova:

docker compose exec -T db pg_restore -U app -d app --clean --if-exists < backup_2026-10-12.dump

MySQL / MariaDB:

docker compose exec -T db sh -c 'mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" --single-transaction --databases app' | gzip > mysql_$(date +%F).sql.gz

U MariaDB 11 se klient jmenuje mariadb-dump. Obnova:

gunzip < mysql_2026-10-12.sql.gz | docker compose exec -T db sh -c 'mysql -u root -p"$MYSQL_ROOT_PASSWORD"'

Záloha libovolného volume přes tar

Pro data, která nejsou databáze (nahrané soubory, konfigurace aplikace), použijte pomocný kontejner:

docker run --rm \
  -v appdata:/data:ro \
  -v "$PWD":/backup \
  alpine tar czf /backup/appdata_$(date +%F).tar.gz -C /data .

Obnova do (nového) volume:

docker volume create appdata
docker run --rm \
  -v appdata:/data \
  -v "$PWD":/backup \
  alpine sh -c "cd /data && tar xzf /backup/appdata_2026-10-12.tar.gz"

Stejný postup slouží k přesunu volume na jiný server.

Pokud aplikace do volume během zálohy zapisuje, je bezpečnější ji na chvíli zastavit (docker compose stop web).

Automatizace cronem

Skript /usr/local/bin/backup-app.sh:

#!/usr/bin/env bash
set -euo pipefail
DEST=/var/backups/app
mkdir -p "$DEST"
cd /srv/app

docker compose exec -T db pg_dump -U app -Fc app > "$DEST/db_$(date +%F_%H%M).dump"

docker run --rm -v app_uploads:/data:ro -v "$DEST":/backup alpine \
  tar czf "/backup/uploads_$(date +%F_%H%M).tar.gz" -C /data .

# smazat zálohy starší 14 dní
find "$DEST" -type f -mtime +14 -delete
sudo chmod +x /usr/local/bin/backup-app.sh
sudo crontab -e
# každou noc ve 3:15
15 3 * * * /usr/local/bin/backup-app.sh >> /var/log/backup-app.log 2>&1

Pravidlo 3-2-1

Záloha na stejném disku jako data vás neochrání před selháním serveru. Držte se pravidla: 3 kopie, 2 různá média, 1 mimo server. Pro odeslání mimo server se hodí rclone (S3, Backblaze B2, Google Drive…) nebo restic, který umí deduplikaci a šifrování:

restic -r sftp:[email protected]:/restic-repo backup /var/backups/app

Testujte obnovu

Záloha, ze které jste nikdy neobnovovali, je jen naděje. Jednou za čas obnovte dump do testovacího kontejneru:

docker run -d --name pgtest -e POSTGRES_PASSWORD=test postgres:16
docker exec -i pgtest createdb -U postgres app
docker exec -i pgtest pg_restore -U postgres -d app < db_2026-10-12_0315.dump
docker exec -it pgtest psql -U postgres app -c '\dt'
docker rm -f pgtest

Pokud chcete skript zálohy přizpůsobit svému serveru, ColdHost AI v režimu Server a DevOps ho s vámi upraví a na připojeném VPS můžete jednotlivé kroky spustit po schválení.