#!/bin/bash
CONTAINER_NAME="my_postgres_container"
DB_USER="postgres_user"
DB_NAME="production_db"
BACKUP_DIR="/opt/backups/db"
# Creăm folderul de backup dacă nu există
mkdir -p "$BACKUP_DIR"
# Backup direct prin stdout, comprimat pe mașina gazdă
docker exec -t "$CONTAINER_NAME" pg_dump -U "$DB_USER" "$DB_NAME" | gzip > "$BACKUP_DIR/backup_db_$(date +%Y%m%d_%H%M%S).sql.gz"
# Ștergem backup-urile mai vechi de 30 de zile ca să nu umplem discul inutil
find "$BACKUP_DIR" -type f -name "backup_db_*.sql.gz" -mtime +30 -deleteAm văzut prea des setup-uri de Docker în care bazele de date rulează pe bind mounts dubioase, iar backup-ul înseamnă un cron job care face un simplu tar pe folderul /var/lib/postgresql/data. E rețeta perfectă pentru dezastru și corupere de date. Astăzi lămurim diferența dintre named volumes și bind mounts și îți arăt cum fac eu backup și restore în producție, testat pe bune de-a lungul anilor.
Named Volumes vs Bind Mounts: Unde e capcana?
Pe scurt, bind mount-ul (-v /calea/mea:/var/lib/mysql) leagă un director specific de pe mașina gazdă în container. Named volume-ul (-v db_data:/var/lib/mysql) lasă Docker să gestioneze el locația pe disc, de obicei undeva în /var/lib/docker/volumes/.
Am avut un proiect acum 3 ani cu vreo 12.000 de utilizatori activi zilnic unde am început cu bind mounts pentru o bază de date PostgreSQL. Pe macOS-ul developerilor, I/O-ul era un coșmar absolut din cauza layer-ului de virtualizare și a sincronizării de fișiere. Când am trecut totul pe named volumes, am obținut un boost de performanță de aproape 40% la scrierile grele.
Trade-off-ul este însă evident. Bind mounts sunt excelente pentru local development, când vrei ca modificările din codul tău Node.js sau PHP să se vadă instant în container fără rebuild. În schimb, pentru baze de date în producție, regula de aur este să folosești exclusiv named volumes. Docker se ocupă singur de permisiuni, de UID/GID și performanța I/O este nativă. Dezavantajul? Nu poți să intri ușor cu FileZilla sau din terminalul gazdei să modifici fișierele direct pe disc, dar, sincer, nici nu ar trebui să faci asta într-un mediu de producție.
De ce „tar pe folder” înseamnă sinucidere curată
Dacă baza ta de date rulează și scrie activ în fișiere, iar tu faci o copie de siguranță a folderului de date folosind rsync sau tar, ai toate șansele să obții un backup corupt. PostgreSQL sau MySQL țin date în memorie (shared buffers) și scriu asincron pe disc. Dacă prinzi o scriere la jumătate în timpul rulării utilitarului de arhivare, ai pierdut baza de date.
Pentru un backup corect, trebuie să folosești utilitarele native ale bazei de date (pg_dump sau mysqldump), rulate chiar în interiorul containerului, care știu să asigure consistența tranzacțională.
Scriptul de backup pe care îl folosesc în producție
Iată cum fac eu un backup curat la o bază de date Postgres care rulează într-un container. Nu ai nevoie de unelte complexe sau servicii SaaS scumpe, un simplu script de bash și un cron job sunt suficienți pentru a dormi liniștit noaptea. Scriptul de mai jos rulează pg_dump direct în container, scoate stream-ul de date în afara lui prin stdout, îl comprimă direct cu gzip pe gazdă și îl salvează cu timestamp.
Restore-ul: Singura dovadă că ai un backup real
Un backup netestat nu este backup. Am pățit o singură dată să am nevoie de un restore în producție după un update eșuat de schemă și să descopăr că fișierul .sql.gz era gol. Parola de Postgres fusese schimbată în mediu, iar scriptul dădea eroare silențioasă în cron. De atunci, testez automat restore-ul o dată pe lună într-un container temporar.
Ca să testezi restore-ul din scriptul prezentat, pornești un container Postgres curat (pe un alt port sau local) și rulezi o singură linie de terminal:
gunzip -c /opt/backups/db/backup_db_data_valida.sql.gz | docker exec -i container-postgres-test psql -U user_db -d nume_db
Dacă comanda se termină fără erori și tabelele sunt populate, abia atunci poți spune că ai un backup valid.
Voi cum gestionați backup-urile pentru bazele de date în containere? Mergeți pe soluții integrate în cloud (cum ar fi AWS RDS) sau rulați totul self-hosted cu scripturi similare pe VPS-uri?