Backup & Restore #
Dalam dunia container, data adalah aset paling kritikal. Container Docker bersifat ephemeral — mudah dibuat dan dihancurkan — tetapi data tidak boleh ikut hilang. Setiap database row, setiap uploaded file, setiap log entry yang hilang bisa berarti kerugian finansial, kehilangan trust customer, atau bahkan sanksi regulasi.
Sayangnya, banyak engineer (dan bahkan tim engineering) yang tidak punya strategi backup yang benar untuk data Docker mereka. Mereka backup image, atau backup container, atau tidak backup sama sekali. Semua pendekatan ini bermasalah.
Artikel ini membahas strategi backup & restore yang benar untuk data Docker: apa yang harus dibackup, tooling yang tepat, cara mengotomasi, dan (yang sering dilupakan) cara mengetes bahwa restore benar-benar bekerja. Setelah membaca ini, kamu akan punya fondasi yang solid untuk melindungi data Docker kamu dari segala kemungkinan.
Mindset yang Benar: Backup Data, Bukan Container #
Sebelum masuk ke teknis, ada satu mindset yang harus kamu pegang:
Container = disposable. Data = precious. Backup = data, bukan container.
Ini terdengar sederhana, tapi banyak engineer yang masih melakukannya salah. Mereka berpikir: “Saya akan backup container-nya, kalau rusak tinggal restore container.” Ini bukan backup — ini snapshot runtime yang:
- Berisi data runtime yang mungkin tidak konsisten.
- Berisi konfigurasi yang seharusnya di version control.
- Berisi secret yang tidak boleh ter-commit.
- Besar, lambat, dan tidak portable.
- Tidak bisa di-restore selektif (satu tabel database, satu folder upload).
flowchart TB
APP[App Container<br/>stateless] -->|" data "/| DATA[(Data Layer<br/>volume/database)]
DATA -->|" backup target "| BACKUP[Backup File<br/>.tar / .sql]
APP -.->|" ✗ JANGAN backup "| CONTAINER[Container Snapshot]
CONTAINER -.->|" ✗ Tidak konsisten "| PROBLEM[Data corrupt]
style BACKUP fill:#51cf66,color:#fff
style CONTAINER fill:#ff6b6b,color:#fff
style PROBLEM fill:#ff6b6b,color:#fff
Yang benar: backup data (volume, database dump, file), bukan container. Container bisa dibuat ulang dari image, data harus di-backup secara eksplisit.
Anti-pattern kritis: Jangan pernah backup container Docker dengandocker commitataudocker save. Image hasil commit berisi: data runtime (mungkin tidak konsisten), secret, konfigurasi yang seharusnya di Git, dan noise yang menyulitkan audit. Backup data, bukan container.
Apa yang Harus Dibackup di Docker? #
Tidak semua hal perlu dibackup. Backup yang salah sasaran membuang storage dan waktu. Backup yang kurang sasaran berarti kehilangan data. Pahami klasifikasi berikut:
| Item | Wajib Backup? | Alasan |
|---|---|---|
| Dockerfile | ❌ Tidak | Sudah di version control (Git) |
| docker-compose.yml | ❌ Tidak | Sudah di version control |
| Image Docker | ❌ Tidak | Bisa di-build ulang dari Dockerfile, atau di-pull dari registry |
| Container snapshot (commit) | ❌ Tidak | Anti-pattern, berisi data runtime |
| Docker Volume | ✅ Ya | Data persisten yang tidak ada di tempat lain |
| Database dump | ✅ Ya | Logical backup, lebih aman dari file volume |
| File upload user | ✅ Ya | Aset user, tidak bisa di-recreate |
| Konfigurasi (.env, secrets) | ✅ Ya | Source of truth, tapi harus di-encrypt |
| Log aplikasi | ⚠️ Tergantung SLA | Biasanya di-aggregate ke sistem log terpusat |
| TLS certificate | ✅ Ya | Tidak boleh hilang, susah replace cepat |
flowchart TB
A[Item di Environment Docker] --> B[Di Version Control]
A --> C[Di Registry Image]
A --> D[HARUS di-backup]
B --> B1[Dockerfile]
B --> B2[docker-compose.yml]
B --> B3[Konfigurasi non-secret]
C --> C1[Image Docker]
D --> D1[Volume data]
D --> D2[Database dump]
D --> D3[File upload]
D --> D4[Secret dan cert]
D --> D5[Log penting]
style D fill:#ffd43b
style D1 fill:#ffd43b
style D2 fill:#ffd43b
style D3 fill:#ffd43b
style D4 fill:#ffd43b
style D5 fill:#ffd43b
Prinsip 3-2-1 backup: Simpan 3 copy data, di 2 jenis media berbeda, 1 di lokasi off-site. Untuk data Docker: 1 copy di volume (lokasi aktif), 1 copy di storage lokal berbeda (NFS, second disk), 1 copy di cloud (S3, GCS, Azure Blob).
Backup Volume Docker #
Volume adalah direktori di host. Backup volume = backup isi direktori itu. Tapi ada beberapa pola yang lebih elegan dari cp -r manual.
Melihat Daftar dan Detail Volume #
# Lihat semua volume
docker volume ls
# Filter volume yang dangling (tidak terpakai)
docker volume ls -f dangling=true
# Inspect detail volume
docker volume inspect mysql-data
Output inspect menunjukkan Mountpoint di host:
[
{
"Name": "mysql-data",
"Driver": "local",
"Mountpoint": "/var/lib/docker/volumes/mysql-data/_data",
"CreatedAt": "2026-06-06T12:00:00Z"
}
]
Backup dengan Container Helper #
Pola paling umum: jalankan container ephemeral yang mount volume, archive isinya, simpan ke host.
# Backup volume ke file tar.gz
docker run --rm \
-v mysql-data:/source:ro \
-v $(pwd):/backup \
alpine \
tar czf /backup/mysql-data-$(date +%F).tar.gz -C /source .
Penjelasan:
--rm— container dihapus setelah selesai (ephemeral).-v mysql-data:/source:ro— mount volume read-only untuk backup.-v $(pwd):/backup— mount working directory untuk output file.alpine— image kecil (5 MB) sebagai helper.tar czf ... -C /source .— kompres seluruh isi volume.
Hasilnya: file mysql-data-2026-06-06.tar.gz di working directory host.
Restore dari Backup #
# 1. Buat volume baru (jika belum ada)
docker volume create mysql-data
# 2. Extract backup ke volume
docker run --rm \
-v mysql-data:/target \
-v $(pwd):/backup \
alpine \
tar xzf /backup/mysql-data-2026-06-06.tar.gz -C /target
flowchart LR
BACKUP[backup.tar.gz<br/>di host] -->|tar xzf| CONT[Helper Container]
CONT -->|extract ke /target| VOL[Volume<br/>mysql-data]
style BACKUP fill:#a8d8a8
style VOL fill:#ffd8a8
Backup Multi-Volume Sekaligus #
Untuk setup yang punya banyak volume:
#!/bin/bash
# backup-all-volumes.sh
BACKUP_DIR=/backup/volumes
DATE=$(date +%F)
mkdir -p $BACKUP_DIR/$DATE
for vol in $(docker volume ls -q); do
echo "Backing up volume: $vol"
docker run --rm \
-v $vol:/source:ro \
-v $BACKUP_DIR/$DATE:/backup \
alpine \
tar czf /backup/$vol-$DATE.tar.gz -C /source .
done
# Cleanup backup lama (simpan hanya 30 hari)
find $BACKUP_DIR -type d -mtime +30 -exec rm -rf {} \;
Simpan sebagai script, jalankan via cron. Backup otomatis, retention 30 hari.
Backup Database dengan Logical Dump #
Untuk database, backup file volume saja sering tidak cukup. Volume berisi data file database yang mungkin tidak konsisten saat di-copy (kalau database sedang running). Lebih aman pakai logical backup (SQL dump).
MySQL / MariaDB #
# Backup
docker exec mysql-container \
mysqldump -u root -psecret --all-databases > /backup/mysql-$(date +%F).sql
# Restore
docker exec -i mysql-container \
mysql -u root -psecret < /backup/mysql-2026-06-06.sql
Atau backup hanya database tertentu:
docker exec mysql-container \
mysqldump -u root -psecret mydb > /backup/mydb-$(date +%F).sql
PostgreSQL #
# Backup
docker exec postgres-container \
pg_dump -U postgres mydb > /backup/mydb-$(date +%F).sql
# Restore
docker exec -i postgres-container \
psql -U postgres mydb < /backup/mydb-2026-06-06.sql
Atau kompres langsung:
docker exec postgres-container \
pg_dump -U postgres -Fc mydb > /backup/mydb-$(date +%F).dump
Format -Fc (custom) lebih kecil dan punya fitur restore selektif.
MongoDB #
# Backup
docker exec mongo-container \
mongodump --archive=/tmp/backup.archive
docker cp mongo-container:/tmp/backup.archive /backup/
# Restore
docker cp /backup/backup.archive mongo-container:/tmp/
docker exec mongo-container \
mongorestore --archive=/tmp/backup.archive
SQLite #
# Backup
docker cp app-container:/app/data.db /backup/data-$(date +%F).db
# Restore
docker cp /backup/data-2026-06-06.db app-container:/app/data.db
SQLite adalah single file — backup = copy file. Pastikan tidak ada transaksi aktif (sqlite3 .backup lebih aman dari cp).
Keuntungan logical backup (dump): Konsisten di level transaksi (database di-snapshot di satu titik waktu), portabel ke versi database berbeda, bisa di-restore selektif, dan tidak tergantung filesystem internal database.
Backup dengan Docker Compose #
Di Compose, backup biasanya dilakukan dengan service khusus yang dijalankan on-demand atau via schedule.
Service Backup #
version: "3.9"
services:
app:
image: my-app:1.2
volumes:
- app-data:/app/data
db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
backup:
image: alpine
profiles: ["backup"] # hanya jalan dengan --profile backup
volumes:
- pgdata:/source:ro
- app-data:/source2:ro
- ./backups:/backup
command: >
sh -c "
tar czf /backup/pgdata-$$(date +%F).tar.gz -C /source . &&
tar czf /backup/app-data-$$(date +%F).tar.gz -C /source2 . &&
echo 'Backup selesai'
"
volumes:
app-data:
pgdata:
# Jalankan backup manual
docker compose --profile backup run --rm backup
Keuntungan pola ini:
- Deklaratif — backup config ada di compose file.
- Profil — service backup tidak otomatis jalan saat
compose up, hanya saat dibutuhkan. - Ephemeral —
--rmmemastikan container backup dihapus setelah selesai.
Scheduled Backup dengan Cron #
# /etc/cron.d/docker-backup
# Backup harian jam 2 pagi
0 2 * * * root cd /opt/myapp && /usr/local/bin/docker compose --profile backup run --rm backup >> /var/log/docker-backup.log 2>&1
# Weekly cleanup backup lama (>30 hari)
0 4 * * 0 root find /opt/myapp/backups -type f -mtime +30 -delete
Cron di host menjalankan service backup via Compose, log ke file untuk audit.
Backup ke Cloud Storage #
Backup di host yang sama dengan data = satu titik kegagalan (single point of failure). Backup harus di-copy ke lokasi lain yang independen. Cloud storage (S3, GCS, Azure Blob) adalah pilihan paling umum.
Backup ke AWS S3 #
#!/bin/bash
# backup-to-s3.sh
DATE=$(date +%F)
BACKUP_FILE="db-backup-$DATE.sql"
S3_BUCKET="s3://my-app-backups"
# 1. Dump database
docker exec postgres-container \
pg_dump -U postgres mydb > /tmp/$BACKUP_FILE
# 2. Compress
gzip /tmp/$BACKUP_FILE
# 3. Upload ke S3
aws s3 cp /tmp/$BACKUP_FILE.gz $S3_BUCKET/$BACKUP_FILE.gz
# 4. Cleanup local
rm /tmp/$BACKUP_FILE.gz
# 5. Log
echo "Backup uploaded: $S3_BUCKET/$BACKUP_FILE.gz" >> /var/log/backup.log
# Cron: jalankan tiap hari
0 3 * * * root /opt/scripts/backup-to-s3.sh
Backup ke S3 Langsung dari Container #
Tanpa harus copy ke host dulu:
docker run --rm \
-v pgdata:/source:ro \
-v ~/.aws:/root/.aws:ro \
amazon/aws-cli:latest \
sh -c "tar czf - -C /source . | aws s3 cp - s3://my-backups/pgdata-$(date +%F).tar.gz"
Container amazon/aws-cli punya AWS CLI. Mount volume (read-only) dan AWS credentials, stream langsung ke S3.
Backup ke Google Cloud Storage #
docker run --rm \
-v pgdata:/source:ro \
-v /path/to/gcp-key.json:/key.json:ro \
google/cloud-sdk:latest \
sh -c "tar czf - -C /source . | gsutil cp - gs://my-backups/pgdata-$(date +%F).tar.gz"
Backup ke Azure Blob #
docker run --rm \
-v pgdata:/source:ro \
-v ~/.azure:/root/.azure:ro \
mcr.microsoft.com/azure-cli:latest \
sh -c "tar czf - -C /source . | az storage blob upload -c mybackup -n pgdata-$(date +%F).tar.gz --account-name mystorageaccount --stdin"
Detail penting: Mount credentials (~/.aws,~/.azure) read-only dan pastikan permission-nya sesuai. Jangan pernah bake credentials ke image atau commit ke Git.
Restore — yang Paling Sering Dilupakan #
Backup yang tidak pernah di-restore = backup yang tidak ada. Banyak tim punya backup rutin tapi tidak pernah benar-benar melakukan restore. Saat disaster terjadi, mereka kaget karena:
- File backup corrupt.
- Format backup tidak kompatibel dengan versi database baru.
- Prosedur restore tidak pernah di-tes, dan saat dicoba butuh waktu berjam-jam.
- Kredensial atau dependency restore sudah expired.
Restore harus dites secara berkala. Ini bukan opsional.
Prosedur Test Restore #
PROSEDUR TEST RESTORE (JALANKAN BULANAN):
1. Pilih backup terbaru secara acak
2. Spin up environment terpisah (bukan production!)
- docker compose -f docker-compose.test-restore.yml up -d
3. Restore backup ke environment ini
- Tar extract ke volume
- Atau psql/mysql restore ke database container
4. Verifikasi data:
- Hitung row di tabel kritis (users, orders, products)
- Bandingkan dengan jumlah row di production
- Cek sample data apakah konsisten
5. Smoke test aplikasi:
- Login sebagai user
- Ambil data sample
- Jalankan query kritis
6. Catat hasil di log:
- Tanggal restore
- Ukuran backup
- Waktu restore
- Row count sebelum/sesudah
- Issue yang ditemukan
7. Cleanup:
- docker compose -f docker-compose.test-restore.yml down -v
Runbook Restore #
Setiap backup harus punya runbook yang menjelaskan langkah restore step-by-step:
# Runbook: Restore PostgreSQL dari Backup
## Prasyarat
- Akses SSH ke production server
- File backup di S3: s3://my-backups/postgres/
- Kredensial database (cek di secret manager)
## Langkah Restore
### 1. Stop Aplikasi
\`\`\`bash
docker compose stop app
\`\`\`
Aplikasi di-stop untuk mencegah write ke database selama restore.
### 2. Identifikasi Backup
\`\`\`bash
# Lihat backup terbaru
aws s3 ls s3://my-backups/postgres/ | sort | tail -5
\`\`\`
### 3. Download Backup
\`\`\`bash
aws s3 cp s3://my-backups/postgres/postgres-2026-06-06.sql.gz /tmp/
gunzip /tmp/postgres-2026-06-06.sql.gz
\`\`\`
### 4. Restore ke Database
\`\`\`bash
docker exec -i postgres-container \
psql -U postgres mydb < /tmp/postgres-2026-06-06.sql
\`\`\`
### 5. Start Aplikasi
\`\`\`bash
docker compose start app
\`\`\`
### 6. Smoke Test
- Login ke aplikasi
- Ambil data sample
- Cek log untuk error
## Estimasi Waktu
- Download backup: 5-15 menit (tergantung ukuran)
- Restore: 10-60 menit (tergantung ukuran database)
- Total: 30-90 menit
## Kontak
- DBA on-call: ...
- DevOps on-call: ...
Runbook harus:
- Tercatat di repo atau wiki.
- Di-review dan di-update setiap quarter.
- Di-tes oleh engineer yang berbeda dari yang menulis.
- Diketahui semua anggota tim on-call.
Automasi Backup #
Backup manual = backup yang terlewat. Backup harus otomatis, dengan monitoring agar tahu kalau ada kegagalan.
Pola 1: Cron di Host #
# /etc/cron.d/docker-backup
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Backup harian jam 2 pagi
0 2 * * * root /opt/scripts/backup-volumes.sh >> /var/log/backup.log 2>&1
# Backup database jam 3 pagi
0 3 * * * root /opt/scripts/backup-database.sh >> /var/log/backup.log 2>&1
# Upload ke S3 jam 4 pagi
0 4 * * * root /opt/scripts/backup-to-s3.sh >> /var/log/backup.log 2>&1
Pola 2: Cron Container #
services:
cron:
image: alpine
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro # untuk control Docker
- pgdata:/source:ro
- ./backups:/backup
- ./scripts:/scripts:ro
command: >
sh -c "
echo '0 2 * * * /scripts/backup.sh' > /etc/crontabs/root &&
crond -f -L /dev/stdout
"
Container yang menjalankan cron di dalam Docker. Lebih portable, tapi lebih kompleks (perlu handle sinyal, log, monitoring).
Pola 3: Backup Service Terpusat #
Untuk environment dengan banyak aplikasi, gunakan backup service terpusat (seperti Velero untuk Kubernetes, atau custom orchestrator untuk Docker). Service ini:
- Menjadwalkan backup untuk semua aplikasi.
- Menangani retensi.
- Memantau keberhasilan backup.
- Alert ke tim jika ada kegagalan.
Monitoring Backup #
Backup yang gagal harus alert, bukan silent. Tools:
# Script dengan notifikasi ke Slack
#!/bin/bash
BACKUP_RESULT=$(/opt/scripts/backup-database.sh 2>&1)
if [ $? -ne 0 ]; then
curl -X POST https://hooks.slack.com/services/YOUR/WEBHOOK/URL \
-H 'Content-type: application/json' \
-d "{\"text\": \"❌ Backup GAGAL di $(hostname)\n$BACKUP_RESULT\"}"
else
curl -X POST https://hooks.slack.com/services/YOUR/WEBHOOK/URL \
-H 'Content-type: application/json' \
-d "{\"text\": \"✅ Backup berhasil di $(hostname)\"}"
fi
flowchart LR
A[Cron Job] --> B[Backup Script]
B --> C{Backup<br/>berhasil?}
C -- Ya --> D[Log success]
C -- Tidak --> E[Alert Slack/PagerDuty]
style D fill:#51cf66,color:#fff
style E fill:#ff6b6b,color:#fff
Retensi dan Rotasi Backup #
Backup tanpa retensi = disk penuh. Backup tanpa rotasi = backup terlama yang bisa di-restore adalah yang terbaru, padahal yang terlama yang paling relevan saat audit atau forensik.
Pola Retensi #
| Pola | Deskripsi | Use Case |
|---|---|---|
| Harian 7, mingguan 4, bulanan 12 | 7 backup harian terakhir, 4 mingguan, 12 bulanan | Umum, memenuhi kebanyakan compliance |
| GFS (Grandfather-Father-Son) | Daily, weekly, monthly, yearly | Compliance ketat (regulasi finance) |
| Custom sesuai SLA | Retensi 30/60/90/365 hari | Bergantung SLA dan compliance |
| Immutable backup | WORM storage, tidak bisa dihapus | Anti-ransomware |
Contoh retensi 30 hari dengan cleanup otomatis:
#!/bin/bash
# retention-30-days.sh
BACKUP_DIR=/backup/volumes
# Hapus backup volume yang lebih dari 30 hari
find $BACKUP_DIR -name "*.tar.gz" -mtime +30 -delete
# Hapus backup database yang lebih dari 90 hari
find /backup/db -name "*.sql.gz" -mtime +90 -delete
3-2-1 rule dengan retensi: 3 copy data, di 2 jenis media, 1 off-site, dengan retensi yang memenuhi compliance. Contoh: 1 copy di local volume, 1 copy di NAS lokal (mingguan), 1 copy di S3 (retensi 90 hari), 1 copy di S3 Glacier (retensi 7 tahun untuk compliance).
Enkripsi Backup #
Backup berisi data sensitif. Backup ke cloud storage tanpa enkripsi = data exposure kalau bucket S3 disalah config.
Enkripsi Saat Backup #
# Backup + encrypt dengan GPG
docker exec postgres-container \
pg_dump -U postgres mydb | \
gpg --symmetric --cipher-algo AES256 --output /backup/db-$(date +%F).sql.gpg
Restore:
gpg --decrypt /backup/db-2026-06-06.sql.gpg | \
docker exec -i postgres-container psql -U postgres mydb
Enkripsi di Cloud Storage #
S3, GCS, dan Azure Blob mendukung server-side encryption:
# S3: server-side encryption dengan KMS
aws s3 cp /backup/db.sql.gz s3://my-backups/db.sql.gz \
--server-side-encryption aws:kms \
--ssekms-key-id arn:aws:kms:...
# GCS: server-side encryption (default enabled)
gsutil cp /backup/db.sql.gz gs://my-backups/
# Azure: server-side encryption (default enabled)
az storage blob upload -f /backup/db.sql.gz -c mybackup -n db.sql.gz
Untuk extra security, client-side encryption (GPG, age, sops) sebelum upload.
Backup Anti-Patterns #
1. Backup Image Docker #
# ANTI-PATTERN
docker commit running-container backup:v1
docker save backup:v1 > backup.tar
Image berisi data runtime yang tidak konsisten, bloated, dan tidak aman. Backup data, bukan image.
2. Backup Container (docker export) #
# ANTI-PATTERN
docker export container-name > backup.tar
Container snapshot — file system container pada satu titik waktu. Berisi noise (temporary file, cache), tidak konsisten untuk database, dan tidak bisa di-restore selektif.
3. Backup ke Lokasi yang Sama #
# ANTI-PATTERN
# Backup di disk yang sama dengan volume
docker run -v pgdata:/source -v /backup:/target alpine tar czf /target/db.tar.gz -C /source .
# /backup di disk yang sama dengan /var/lib/docker/volumes
# Disk failure = data DAN backup hilang
Backup harus ke disk berbeda, atau ke cloud.
4. Tidak Test Restore #
# ANTI-PATTERN
# "Backup sukses, tahun lalu sudah restore, pasti masih jalan"
Restore harus di-tes secara berkala. Software upgrade, format backup berubah, dependency hilang, dsb.
5. Backup Tanpa Monitoring #
# ANTI-PATTERN
# "Cron jalan setiap hari, pasti backup sukses"
Backup script bisa gagal karena disk penuh, permission salah, network down, atau command error. Tanpa monitoring, kamu tidak tahu sampai disaster terjadi.
6. Single Account untuk Backup #
# ANTI-PATTERN
# Backup pakai access key yang sama dengan production
# Kalau akun compromised, production DAN backup hilang
Gunakan akun IAM terpisah untuk backup. Limit permission hanya untuk write ke bucket backup.
7. Tidak Dokumentasikan Prosedur #
# ANTI-PATTERN
# "Coba tunggu, saya cari command-nya dulu..."
Saat disaster, kamu butuh restore dalam hitungan menit, bukan berjam-jam explore script. Runbook harus siap dan di-tes.
Backup untuk Use Case Spesifik #
WordPress / CMS #
# Backup files + database
docker exec wordpress-db mysqldump -u root -p$DB_PASSWORD wordpress > /backup/wp-db.sql
docker run --rm -v wp-uploads:/source:ro -v /backup:/target alpine \
tar czf /target/wp-uploads.tar.gz -C /source .
Elasticsearch #
# Snapshot ke shared filesystem
curl -X PUT "localhost:9200/_snapshot/my_backup/snap_$(date +%F)" \
-H 'Content-Type: application/json' -d '{}'
Elasticsearch punya API snapshot native. Lebih reliable dari copy file data.
Redis #
# Trigger save dan copy file dump
docker exec redis-container redis-cli BGSAVE
docker cp redis-container:/data/dump.rdb /backup/redis-$(date +%F).rdb
Atau aktifkan AOF (Append Only File) di redis.conf untuk durability.
MinIO / Object Storage #
MinIO punya mc client untuk mirror ke bucket lain. Backup object storage dengan mirror ke bucket S3/GCS lain.
Disaster Recovery — Lebih dari Sekadar Backup #
Backup adalah komponen disaster recovery, tapi bukan satu-satunya. DR yang komprehensif meliputi:
flowchart TB
A[Disaster Recovery] --> B[Backup]
A --> C[Replication]
A --> D[Monitoring]
A --> E[Runbook]
A --> F[Testing]
B --> B1[Rutin ke off-site]
C --> C1[Multi-region/AZ]
D --> D1[Alert + healthcheck]
E --> E1[Prosedur restore]
F --> F1[Test restore berkala]
style A fill:#ffd43b
- Backup — copy data ke lokasi lain.
- Replication — data live di beberapa tempat (multi-AZ, multi-region).
- Monitoring — alert kalau ada kegagalan backup atau replikasi.
- Runbook — prosedur restore yang terdokumentasi.
- Testing — verifikasi berkala bahwa restore benar-benar bekerja.
Untuk kebanyakan aplikasi, kombinasi backup + monitoring + testing sudah cukup. Untuk aplikasi mission-critical, tambahkan replication dan automated failover.
Tools dan Utilities #
Untuk Backup #
| Tool | Fungsi |
|---|---|
tar |
Archive file/direktori |
pg_dump, mysqldump |
Database logical backup |
mongodump |
MongoDB backup |
redis-cli BGSAVE |
Redis snapshot |
aws s3 cp |
Upload ke S3 |
gsutil cp |
Upload ke GCS |
az storage blob upload |
Upload ke Azure Blob |
restic |
Encrypted, deduplicated backup |
borgbackup |
Deduplicated, compressed backup |
duplicity |
Encrypted bandwidth-efficient backup |
Untuk Monitoring #
| Tool | Fungsi |
|---|---|
| Cron + log + alert script | Monitoring sederhana |
| Cronitor | Monitoring cron job eksternal |
| Healthchecks.io | Ping-based monitoring |
| Prometheus + Alertmanager | Monitoring terpusat |
| Datadog, New Relic | SaaS monitoring |
Untuk Restore Testing #
| Pendekatan | Fungsi |
|---|---|
| Separate test environment | Restore ke env terpisah, verifikasi |
| Automated restore + verify | Script restore + row count check |
| Chaos engineering | Test failure scenario secara berkala |
Checklist Backup & Restore #
Gunakan checklist ini untuk memastikan kamu punya backup yang solid:
STRATEGI BACKUP:
□ Data di-backup, bukan container/image
□ Backup harian untuk data aktif
□ Backup mingguan/bulanan untuk retensi panjang
□ Backup ke off-site (cloud / remote location)
□ Backup di-encrypt (in transit + at rest)
□ Retensi sesuai compliance (30/90/365 hari)
OTOMASI:
□ Backup dijalankan via cron / scheduler
□ Backup di-monitor (alert kalau gagal)
□ Log backup di-archive untuk audit
□ Cleanup backup lama otomatis
RESTORE:
□ Prosedur restore terdokumentasi di runbook
□ Test restore dilakukan bulanan
□ Restore time (RTO) diukur
□ Restore point (RPO) diukur dan dipenuhi
KEAMANAN:
□ Backup file di-encrypt
□ Access key untuk backup terpisah dari production
□ Backup bucket tidak public
□ Retention policy untuk akses backup
DRILL:
□ Engineer berbeda bisa melakukan restore
□ Runbook di-review quarterly
□ Tim on-call tahu prosedur restore
□ Backup diasuransikan (untuk data kritikal)
Ringkasan #
- Backup data, bukan container. Container = disposable, data = precious. Backup image atau container adalah anti-pattern — berisi data tidak konsisten, secret, dan noise.
- Yang harus di-backup: volume (data persisten), database dump (logical backup), file upload user, secret dan TLS certificate, dan konfigurasi kritis. Yang TIDAK perlu: Dockerfile, compose file (sudah di Git), image (bisa di-build ulang).
- Tool backup:
taruntuk volume archive,pg_dump/mysqldumpuntuk database logical backup,mongodumpuntuk MongoDB. Selalu mount volume read-only saat backup.- Docker Compose backup service: gunakan
profiles: ["backup"]agar service backup hanya jalan saat dibutuhkan. Jalankan dengandocker compose --profile backup run --rm backup.- Cloud backup: upload backup ke S3, GCS, atau Azure Blob untuk durability. Gunakan akun IAM terpisah dengan permission terbatas. Enkripsi dengan KMS atau client-side.
- Prinsip 3-2-1: 3 copy data, 2 jenis media, 1 off-site. Dengan retensi yang memenuhi compliance (30/90/365 hari).
- Restore harus di-tes berkala. Backup yang tidak pernah di-restore = backup yang tidak ada. Test restore bulanan ke environment terpisah, verifikasi row count dan smoke test aplikasi.
- Runbook restore harus terdokumentasi, di-review quarterly, dan diketahui semua anggota tim on-call. Restore time (RTO) dan restore point (RPO) harus diukur.
- Monitoring backup: alert ke Slack/PagerDuty kalau backup gagal. Silent failure = data loss tanpa sadar. Cron job tanpa monitoring adalah bom waktu.
- Anti-patterns yang harus dihindari: backup image, backup ke lokasi sama, tidak test restore, single IAM account, tanpa monitoring, tanpa dokumentasi.
- Tools berguna: restic, borgbackup, duplicity untuk encrypted backup. Cronitor, Healthchecks.io untuk monitoring cron. Test environment terpisah untuk verifikasi restore.
- Ingat: Container bisa dibuat ulang, data tidak. Backup adalah jaring pengaman terakhir — investasikan waktu dan storage yang cukup.
← Sebelumnya: Volume vs Bind Mount Berikutnya: Sharing Data →