Penutup Chapter Mount Read-Only menyerahkan kita kepada satu kenyataan yang tidak bisa dinegosiasi: penguncian hanya melindungi data dari tangan yang salah menulis, sedangkan kegagalan disk, kesalahan docker volume rm, atau ransomware yang menyapu seluruh host tetap sanggup melahap volume apa pun dalam sekejap. Volume memang hidup sebagai direktori di disk host — wilayah yang sama rentannya dengan direktori lain di mesin kita — sehingga pertanyaannya bukan apakah perlu backup, melainkan bagaimana cara membungkus isi volume dengan benar. Tantangan teknisnya khas Docker: isi volume bersemayam di bawah /var/lib/docker/volumes/, wilayah yang dikuasai daemon dan tidak praktis disalin dengan cp biasa dari user host. Jawaban resminya elegan: biarkan container sendiri yang membaca volumenya, dan arsipkan isinya dari dalam.

Pola Helper Container #

Volume data-web masih menyimpan seluruh cerita section ini: berkas bawaan nginx hasil copy-up, halo.txt dari Chapter Volume, dan nota.txt yang ditulis helper pada Chapter Mount Read-Only. Membungkus semua itu hanya butuh satu perintah dengan dua mount:

bash
$ mkdir -p backup
$ docker run --rm \
    -v data-web:/data:ro \
    -v "$(pwd)/backup:/backup" \
    alpine:3.20 \
    tar czf /backup/data-web.tar.gz -C /data .

Perintah selesai tanpa satu baris output pun — tar hanya bersuara ketika ada yang gagal. Bukti bahwa pekerjaan itu benar-benar terjadi mendarat sebagai berkas host biasa:

bash
$ ls -lh backup/

Output yang Dihasilkan:

text
total 4.0K
-rw-r--r-- 1 budi budi 612 Okt 13 16:08 data-web.tar.gz

Mari kita telaah pola helper container ini bagian demi bagian:

  1. -v data-web:/data:ro — volume sumber dipasang ke /data dengan mode read-only; helper tidak mungkin merusak data yang sedang diarsipkan, teknik penguncian yang kita warisi langsung dari Chapter Mount Read-Only.
  2. -v "$(pwd)/backup:/backup" — direktori backup di direktori kerja host di-bind-mount ke /backup; arsip yang ditulis helper mendarat di host sebagai berkas biasa yang bisa disalin ke USB, dikirim lewat scp, atau dibaca tool backup kantor apa pun.
  3. alpine:3.20 sebagai helper — image 7.8MB berisi tar sudah lebih dari cukup; tidak ada gunanya membangkitkan container besar untuk pekerjaan arsip.
  4. tar czf /backup/data-web.tar.gz — c membuat arsip, z memampatkan dengan gzip, f menentukan nama berkas keluaran di bind mount.
  5. -C /data . — tar berpindah dulu ke /data lalu mengarsipkan .; trik -C ini membuat nama berkas di dalam arsip relatif dan bersih, sehingga hasil ekstraksi tidak menumpuk direktori data-web tambahan.
  6. --rm — container helper lenyap begitu tar selesai; yang tertinggal hanya arsip di host dan volume yang utuh.

Memverifikasi Isi Arsip #

Arsip yang belum pernah diverifikasi bukan backup — melainkan harapan. Sebelum bergantung padanya, kita intip daftar isinya dari sisi host:

bash
$ tar -tzf backup/data-web.tar.gz

Output yang Dihasilkan:

text
./
./50x.html
./halo.txt
./index.html
./nota.txt

Mari kita telaah daftar itu baris demi baris:

  1. ./ — direktori akar arsip itu sendiri; tanda bahwa -C /data . bekerja seperti yang kita rencanakan.
  2. ./index.html dan ./50x.html — berkas bawaan nginx yang tersalin ke volume lewat mekanisme copy-up saat volume kosong pertama kali dipasang ke container nginx pada Chapter Volume.
  3. ./halo.txt — berkas legendaris section ini, ikut terarsip utuh.
  4. ./nota.txt — jejak helper read-write dari Chapter Mount Read-Only; volume memang menyimpan seluruh riwayatnya, dan backup membekukan riwayat itu apa adanya.

Restore ke Volume Baru #

Pemulihan yang aman tidak pernah menimpa volume asal — kita menuangkan arsip ke volume baru yang bersih, lalu membuktikan isinya hidup. Volume tujuan dibuat lebih dulu agar namanya pasti terkendali:

bash
$ docker volume create data-web-pulih

Output yang Dihasilkan:

text
data-web-pulih

Sekarang helper kedua menuangkan arsip ke volume baru itu. Perhatikan bahwa posisi :ro kali ini berpindah tempat:

bash
$ docker run --rm \
    -v data-web-pulih:/data \
    -v "$(pwd)/backup:/backup:ro" \
    alpine:3.20 \
    tar xzf /backup/data-web.tar.gz -C /data

Sama seperti backup, perintah restore selesai tanpa output. Ujian pamungkasnya adalah menyalakan container sungguhan di atas volume pulihan:

bash
$ docker run -d --name web-pulih \
    -p 8082:80 \
    -v data-web-pulih:/usr/share/nginx/html \
    nginx

Output yang Dihasilkan:

text
3ea70f641b403c77b7aeb6f1bef779dc2a802064314ff948ac684ec5593a9835
bash
$ curl localhost:8082/halo.txt

Output yang Dihasilkan:

text
halo

Mari kita telaah rangkaian pemulihan di atas:

  1. -v data-web-pulih:/data tanpa :ro — volume tujuan justru harus read-write karena tar xzf akan menulis ke sana; kebalikan sempurna dari helper backup yang mengunci sumbernya.
  2. -v "$(pwd)/backup:/backup:ro" — arsip sumber dikunci read-only; saat pemulihan, justru arsip yang perlu dilindungi dari tangan gemuruh.
  3. Volume terisi sebelum nginx menyala — karena volume data-web-pulih sudah diisi helper restore sebelum container nginx dijalankan, mekanisme copy-up tidak pernah menyentuhnya; yang tersaji di port 8082 murni isi arsip.
  4. curl mengembalikan isi asli — satu kata halo itu adalah isi halo.txt persis seperti yang ditulis pada Chapter Volume; inilah definisi backup yang sehat: arsip, pemulihan, dan bukti.

Bentuk Panjang –mount #

Dua helper di atas memakai flag -v yang ringkas. Bentuk panjang --mount menawarkan hal yang sama dengan ejaan yang lebih eksplisit — pilihan yang sering dipilih tim untuk skrip yang dibaca banyak orang:

bash
$ docker run --rm \
    --mount type=volume,source=data-web,destination=/data,readonly \
    --mount type=bind,source="$(pwd)/backup",target=/backup \
    alpine:3.20 \
    tar czf /backup/data-web.tar.gz -C /data .

Setiap pasangan kunci-nilai pada --mount menyebut jenis mount, sumber, tujuan, dan mode secara gamblang, sehingga niat perintah terbaca tanpa menghafal urutan field flag -v. Hasil akhirnya identik dengan versi pendek — arsip yang sama muncul di backup/.

Otomasi Harian dengan cron #

Backup yang mengandalkan ingatan manusia akan berhenti pada minggu kedua. Di server produksi, pola helper container ini hidup di crontab dan berjalan sendiri setiap dini hari:

bash
$ crontab -e

Baris-baris berikut ditambahkan ke berkas crontab:

text
0 2 * * * docker run --rm -v data-web:/data:ro -v /srv/backup:/backup alpine:3.20 tar czf /backup/data-web-$(date +\%Y\%m\%d).tar.gz -C /data .
30 2 * * * find /srv/backup -name 'data-web-*.tar.gz' -mtime +7 -delete

Mari kita telaah kedua baris jadwal itu:

  1. 0 2 * * * — setiap hari pukul 02:00 helper container membungkus data-web menjadi arsip bertanggal, sehingga setiap malam menghasilkan berkas seperti data-web-20261013.tar.gz.
  2. \% yang terlihat aneh itu wajib — cron memotong baris perintah pada karakter % mentah dan menjadikannya pergantian baris; setiap % milik date harus ditulis \% agar sampai ke shell sebagai % yang sebenarnya.
  3. 30 2 * * * dengan find -mtime +7 -delete — setengah jam kemudian, arsip yang berumur lebih dari tujuh hari dihapus otomatis; rotasi ini menjaga direktori /srv/backup tetap ramping tanpa perlu ritual pembersihan manual.
  4. Syarat senyap — user pemilik crontab harus punya akses ke daemon Docker, persis pembahasan grup docker pada Chapter Mengatur Akses Docker di Section Instalasi dan Konfigurasi.

Tabel Perintah Backup dan Restore #

TujuanPerintah inti
Membungkus volume menjadi arsipdocker run --rm -v data-web:/data:ro -v $(pwd)/backup:/backup alpine:3.20 tar czf /backup/data-web.tar.gz -C /data .
Memverifikasi isi arsiptar -tzf backup/data-web.tar.gz
Menyiapkan volume pemulihandocker volume create data-web-pulih
Menuangkan arsip ke volumedocker run --rm -v data-web-pulih:/data -v $(pwd)/backup:/backup:ro alpine:3.20 tar xzf /backup/data-web.tar.gz -C /data
Menguji volume pulihandocker run -d --name web-pulih -p 8082:80 -v data-web-pulih:/usr/share/nginx/html nginx

Kita tutup dengan merapikan panggung — container web-pulih sudah menuntaskan tugas pembuktian, sedangkan arsip backup/data-web.tar.gz sengaja kita simpan karena berkas itu akan menjadi bagasi pada perjalanan berikutnya:

bash
$ docker rm -f web-pulih

Output yang Dihasilkan:

text
web-pulih

Sebab backup hanyalah setengah dari keselamatan data; setengah yang lain adalah memindahkan data ke tempat yang benar pada saat yang benar: pindah server, naik kelas infrastruktur, atau sekadar mengganti nama volume yang dipakai produksi. Chapter Migrasi Data Container membedah tiga strategi pemindahan — arsip berjalan kaki lewat scp, salinan langsung antar volume lewat pipa tar, dan konversi bind mount menjadi volume — lengkap dengan jebakan kepemilikan berkas yang menunggu di ujungnya.

Referensi #

  • Volumes — pola resmi backup, restore, dan migrasi volume dengan helper container.
  • docker volume — referensi perintah docker volume create, ls, dan rm.
  • docker container run — flag -v dan bentuk panjang --mount untuk helper container.