Cara Backup dan Upgrade Stack Docker Compose dengan Aman
Pelajari langkah backup stack Docker Compose yang benar agar data tidak hilang. Panduan ini mencakup cara dump database, menyalin volume, dan prosedur upgrade tanpa risiko.
Apa saja yang harus ada dalam cadangan stack Docker Compose
Cadangan stack Docker Compose harus memuat empat hal terpisah, dan kehilangan salah satunya akan membuat aplikasi tidak dapat dipulihkan: file compose, .env di sampingnya, isi setiap volume, dan dump database yang ditulis oleh klien database itu sendiri. Menyalin file database saat containernya berjalan bukanlah sebuah cadangan. Proses upgrade menggunakan daftar yang sama ditambah satu aturan: buat cadangan sebelum Anda melakukan pull, karena migrasi skema dirancang untuk berjalan maju dan sebagian besar proyek tidak menyediakan cara untuk kembali ke versi sebelumnya.
Semua langkah di bawah mengasumsikan stack sudah di-deploy dan docker compose ps menunjukkan bahwa stack tersebut sedang berjalan. Contoh-contoh ini menggunakan direktori proyek di /srv/myapp dengan service bernama app dan db. Ganti dengan nama Anda sendiri. Perintah yang digunakan sengaja dibuat generik, karena bagian yang krusial, yaitu volume dan database, bekerja dengan cara yang sama apa pun aplikasinya.
Tentukan apa yang sebenarnya disimpan oleh stack Anda
cd /srv/myapp
docker compose ps
docker compose config --volumes
docker volume ls --filter label=com.docker.compose.project=myappdocker compose config --volumes mencetak nama singkat dari volume bernama yang dideklarasikan oleh file Anda. docker volume ls mencetak nama yang sebenarnya dimiliki volume tersebut di disk. Kedua daftar ini berbeda karena Compose menambahkan nama proyek di depannya: volume yang ditulis sebagai db_data di dalam file akan ada sebagai myapp_db_data. Nama proyek secara default adalah nama direktori, sehingga mengganti nama direktori akan mengarahkan stack ke sekumpulan volume kosong yang baru dan membiarkan volume lama tetap ada dengan data Anda di dalamnya. Setiap perintah di bawah ini memerlukan nama asli dari docker volume ls.
Bind mount tidak muncul di kedua daftar tersebut. Di dalam file compose, bind mount adalah entri dengan path host di sebelah kiri titik dua, ./config:/app/config. Bind mount adalah direktori biasa pada host, sehingga alat standar dapat mengaksesnya. Volume bernama berada di bawah /var/lib/docker/volumes/, dan docker volume inspect --format '{{.Mountpoint}}' myapp_db_data mencetak path tepat dari salah satu volume tersebut. Jenis yang digunakan oleh stack Anda akan mengubah cara Anda menyalinnya, dan bind mount dibandingkan volume bernama membahas pertukaran (trade-off) tersebut secara lengkap.
Sekarang, kelompokkan apa yang telah Anda temukan ke dalam dua grup. Beberapa volume menyimpan state yang tidak dapat dibuat ulang: file yang diunggah, kunci yang dihasilkan, database itu sendiri, dan apa pun yang diketik pengguna ke dalam aplikasi. Grup lainnya menyimpan data turunan seperti thumbnail dan indeks pencarian, yang dapat dibangun kembali oleh aplikasi itu sendiri. Mencadangkan grup kedua hanya membuang ruang disk dan waktu pemulihan tanpa memberikan manfaat apa pun. Volume cache Redis adalah contoh paling jelas: kehilangannya hanya menyebabkan satu permintaan pertama yang lambat.
Cadangkan file compose dan file .env
Kedua file tersebut berada di host secara berdampingan, dan tidak ada satu pun yang berada di dalam volume. .env menyimpan kata sandi basis data, secret aplikasi, dan token API apa pun, sehingga file inilah yang mengubah tumpukan volume kembali menjadi aplikasi yang berfungsi. File ini juga biasanya tercantum dalam .gitignore, yang berarti rencana "konfigurasi saya ada di git" mengecualikan satu file yang paling penting. Menyimpan secret dalam file env adalah pola yang tepat, dan hal ini memberikan kewajiban yang sepadan pada cadangan Anda.
sudo install -d -m 700 -o "$USER" -g "$(id -gn)" /srv/backups/myapp
cp -a compose.yaml .env /srv/backups/myapp/
chmod 600 /srv/backups/myapp/.envSalin setiap file compose yang digunakan stack, bukan hanya file yang pertama. Stack yang dijalankan dengan -f compose.yaml -f compose.prod.yaml memerlukan kedua file tersebut agar dapat kembali dengan cara yang sama, dan bagaimana beberapa file compose digabungkan menentukan nilai mana yang sebenarnya sampai ke container.
Satu peringatan mengaitkan .env dengan volume. Image resmi Postgres membaca POSTGRES_PASSWORD hanya saat menginisialisasi direktori data yang kosong. Mengubah nilai tersebut di kemudian hari tidak akan mengubah kata sandi di dalam basis data. Memulihkan volume bulan lalu di samping .env hari ini akan menyebabkan aplikasi gagal terhubung dengan FATAL: password authentication failed for user "appuser", meskipun kedua file terlihat benar saat diperiksa. Simpan .env dan volume dari momen yang sama secara bersamaan dalam cadangan yang sama.
Dump database menggunakan klien bawaannya
Server basis data menulis ke berkasnya secara terus-menerus. tar dari /var/lib/postgresql/data yang diambil saat server berjalan akan menyalin beberapa halaman dari sebelum penulisan dan beberapa dari sesudahnya, sehingga arsip tersebut berisi campuran momen yang mungkin tidak dapat diputar ulang. Alat dump membaca di dalam satu transaksi, sehingga berkas tersebut menyimpan satu momen yang konsisten. Perbedaan itulah yang memisahkan cadangan (backup) dari sekadar salinan.
docker compose exec -T db sh -c \
'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' \
> /srv/backups/myapp/db-$(date +%F).dumpPertahankan -T. Flag ini mematikan alokasi TTY, dan dengan TTY terpasang, Docker akan menerjemahkan aliran output saat menuju shell Anda, yang akan merusak dump biner. Anda tidak akan mengetahui hal ini sampai proses restore gagal. Tanda kutip tunggal juga penting: tanda ini mencegah shell host Anda melakukan ekspansi pada $POSTGRES_USER, sehingga shell di dalam kontainer yang melakukannya, menggunakan nilai yang sudah ditetapkan di dalam berkas compose. -Fc menulis dalam format kustom, yang melakukan kompresi saat berjalan dan memungkinkan pg_restore untuk mengambil objek darinya nanti.
Role dan kata sandinya berada di luar basis data tunggal mana pun, jadi ambil juga data tersebut:
docker compose exec -T db sh -c 'pg_dumpall -U "$POSTGRES_USER" --globals-only' \
> /srv/backups/myapp/globals.sqlKemudian periksa apakah berkas tersebut adalah dump dan bukan pesan error:
ls -lh /srv/backups/myapp/
head -c 5 /srv/backups/myapp/db-$(date +%F).dumpDump format kustom dimulai dengan lima byte PGDMP. Berkas dengan nol byte, atau yang dimulai dengan pg_dump:, berarti perintah tersebut gagal. Shell membuat berkas output sebelum perintah dijalankan, sehingga dump yang gagal tetap meninggalkan berkas dengan nama dan stempel waktu yang terlihat meyakinkan. Itu adalah kegagalan cadangan senyap yang paling umum terjadi.
Untuk MariaDB atau MySQL, kliennya berubah namun bentuknya tidak:
docker compose exec -T db sh -c \
'mariadb-dump -u root -p"$MARIADB_ROOT_PASSWORD" --single-transaction --databases "$MARIADB_DATABASE"' \
> /srv/backups/myapp/db-$(date +%F).sql--single-transaction memberikan dump yang konsisten dari tabel InnoDB tanpa memblokir penulis. Pada image MySQL, perintahnya adalah mysqldump dan variabelnya adalah MYSQL_ROOT_PASSWORD dan MYSQL_DATABASE. Pada image MariaDB saat ini, mysqldump masih berfungsi sebagai nama kompatibilitas untuk mariadb-dump. Perhatikan bahwa kata sandi yang diberikan pada baris perintah akan terlihat di daftar proses kontainer selama dump berjalan.
SQLite memerlukan penanganan khusus. Basis datanya berupa satu berkas, tetapi transaksi terbaru mungkin masih berada di berkas -wal terpisah di sampingnya, sehingga menyalin .db saja akan membuat basis data kehilangan penulisan terbaru. Jika image menyertakan klien, sqlite3 /data/app.db ".backup '/data/app-backup.db'" akan menulis salinan yang konsisten saat aplikasi berjalan. Jika tidak, hentikan kontainer dan salin berkas .db bersama dengan pendampingnya, -wal dan -shm.
Jika basis data Anda berjalan di host alih-alih di dalam stack, perintah yang sama berlaku tanpa awalan docker compose exec, dan menjalankan basis data di Docker atau di host layak dibaca sebelum pembangunan ulang Anda berikutnya.
Menangkap volume
Volume bernama tidak memiliki path host yang harus Anda edit secara manual, jadi mount volume tersebut ke dalam container sementara dan arsipkan dari sana.
docker run --rm \
-v myapp_uploads:/data:ro \
-v /srv/backups/myapp:/backup \
alpine:3 tar czf /backup/uploads.tar.gz -C /data .Container pembantu me-mount volume dalam mode read-only di /data dan direktori cadangan Anda di /backup, lalu menulis arsip ke sisi host. --rm menghapus container pembantu segera setelah tar selesai. :ro sangat penting, karena perintah tar yang salah ketik tidak akan merusak sumber data. -C /data . adalah hal yang membuat proses restore berhasil di tempat yang tepat: perintah ini menyimpan setiap path relatif terhadap root volume. Jika Anda menulis tar czf /backup/uploads.tar.gz /data, setiap path akan memiliki awalan data/, sehingga proses restore akan membuat /data/data di dalam volume dan aplikasi akan melihat direktori kosong. Arsip tersebut dimiliki oleh root, karena tar dijalankan sebagai root di dalam container. Jalankan sudo chown "$USER" /srv/backups/myapp/uploads.tar.gz jika hal itu menghambat Anda, dan baca bagaimana PUID dan PGID menentukan kepemilikan file jika file yang di-restore tidak dapat dibaca oleh aplikasi.
Jalankan perintah ini satu kali untuk setiap volume bernama. Bind mount tidak memerlukan container sama sekali: tar czf /srv/backups/myapp/config.tar.gz -C /srv/myapp/config . melakukan tugas yang sama langsung di host.
Tentukan untuk setiap volume apakah aplikasi harus dihentikan. Proses tar langsung pada volume yang sedang ditulis oleh aplikasi dapat menangkap file di tengah proses penulisan. Untuk direktori unggahan, di mana file ditulis sekali dan kemudian hanya dibaca, risiko tersebut kecil. Untuk hal lainnya, hentikan service tersebut selama proses penyalinan dengan docker compose stop app, lalu docker compose start app. stop membiarkan container dan volume tetap ada, yang memang merupakan tujuan Anda di sini, dan perbedaan antara down dan stop layak dipahami dengan pasti sebelum Anda mengetik salah satunya.
Jangan menganggap tar dari volume database sebagai cadangan database Anda. Dump adalah cadangan yang sebenarnya. Arsip volume dari database yang dihentikan hanyalah jalur pembangunan ulang cepat yang berguna dan tidak lebih.
Urutan operasi
- Salin file compose dan
.envke dalam direktori cadangan. - Lakukan dump basis data saat masih berjalan.
- Hentikan kontainer aplikasi jika volumenya berubah di tempat.
- Arsipkan setiap volume bernama dan setiap direktori bind-mount.
- Jalankan kembali apa pun yang Anda hentikan, lalu konfirmasi dengan
docker compose ps. - Catat tag image dan digest yang dijalankan oleh stack tersebut.
- Salin seluruh direktori cadangan keluar dari server ini.
Langkah 7 adalah langkah yang sering ditunda oleh pengguna.
Memindahkan salinan data dari server
Cadangan yang disimpan pada disk yang sama dengan tumpukan aplikasi hanya melindungi Anda dari kesalahan sendiri, bukan dari hal lain. Satu volume yang gagal, satu server yang terhapus, atau satu akun yang hilang akan melenyapkan kedua salinan tersebut secara bersamaan. Kirim direktori tersebut ke penyimpanan di luar VPS ini, sesuai jadwal, dengan kebijakan retensi. restic backups from a VPS membahas pengaturan repositori, flag retensi, dan perintah pemeriksaan, sehingga hal tersebut tidak perlu diulang di sini.
restic juga dapat membaca dump langsung dari pipe, yang menjaga database teks biasa agar tidak tersimpan di disk sama sekali:
docker compose exec -T db sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' \
| restic backup --stdin --stdin-filename db.dumpApa pun alat yang Anda gunakan, masukkan jadwal ke dalam systemd timer atau cron job, dan buat agar pekerjaan tersebut melaporkan kegagalan ke tempat yang akan Anda pantau. Skrip cadangan yang keluarannya tidak terpantau adalah skrip cadangan yang bisa berhenti bekerja selama enam bulan tanpa diketahui siapa pun.
Buktikan cadangan berfungsi dengan latihan pemulihan
Cadangan yang belum pernah dipulihkan hanyalah sebuah hipotesis. Latihan di bawah ini melakukan pemulihan ke dalam tumpukan (stack) kedua yang berjalan di samping tumpukan pertama, sehingga produksi tetap melayani trafik dan tidak ada perintah yang Anda ketik dapat memengaruhinya.
Mekanismenya terletak pada nama proyek. Compose mengambil nama tersebut dari nama direktori dan mencapnya pada setiap kontainer serta volume yang dibuatnya. Salin cadangan ke direktori baru dan tumpukan yang dipulihkan akan mendapatkan volumenya sendiri secara otomatis.
sudo install -d -m 700 -o "$USER" -g "$(id -gn)" /srv/myapp-restore
cd /srv/myapp-restore
cp /srv/backups/myapp/compose.yaml /srv/backups/myapp/.env .Edit file compose yang telah disalin agar port host yang dipublikasikan tidak bertabrakan dengan tumpukan yang sedang berjalan, gunakan 18080:8080 sebagai pengganti 8080:8080, atau ubah variabel yang mengaturnya di dalam .env yang telah disalin. Kemudian buat kontainer dan volume kosongnya tanpa menjalankan apa pun:
docker compose create
docker volume ls --filter label=com.docker.compose.project=myapp-restorePerintah kedua seharusnya menampilkan nama volume yang sama dengan produksi dengan awalan myapp-restore_. Isi volume tersebut, jalankan basis data secara terpisah, dan muat dump:
docker run --rm -v myapp-restore_uploads:/data -v /srv/backups/myapp:/backup \
alpine:3 tar xzf /backup/uploads.tar.gz -C /data
docker compose up -d db
docker compose exec -T db sh -c \
'pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --clean --if-exists' \
< /srv/backups/myapp/db-2026-08-16.dump--clean --if-exists menghapus setiap objek sebelum membuatnya kembali, yang membuat pemulihan dapat diulang. Tanpanya, eksekusi kedua ke dalam basis data yang sudah berisi tabel tersebut akan berhenti dengan pg_restore: error: could not execute query: ERROR: relation "users" already exists.
Kemudian jalankan sisanya dan periksa dengan cara yang dilakukan pengguna:
docker compose up -d --wait
docker compose exec -T db sh -c 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt"'
docker compose logs --tail=50docker compose up -d --wait memblokir proses hingga setiap layanan melaporkan status berjalan atau sehat, dan keluar dengan kode non-nol jika ada yang gagal, yang membuat langkah ini dapat dibuat skrip. Jika sebuah layanan tidak pernah mencapai status sehat, docker compose ps akan menampilkan statusnya, dan Compose healthchecks menjelaskan apa yang dibaca oleh kolom tersebut. Selanjutnya, buka aplikasi pada port alternatif dan masuk dengan akun asli. Tulis satu catatan dan buka satu file yang tersimpan di dalam volume. Pasangan tersebut adalah buktinya: dump telah dipulihkan, volume telah dipulihkan, dan keduanya sinkron satu sama lain. Latihan yang hanya membuktikan halaman login dapat dimuat tidak membuktikan apa pun mengenai data Anda.
Hapus latihan tersebut setelah berhasil:
docker compose down -vIni adalah satu-satunya tempat di mana -v merupakan flag yang tepat. Di direktori produksi, perintah yang sama akan menghapus volume yang sedang Anda coba lindungi.
Cara meningkatkan versi Compose stack
Baca catatan rilis untuk setiap versi di antara versi yang Anda jalankan saat ini dan versi yang dituju, lalu cari kata kunci breaking dan migration. Proyek yang tidak mendukung lompatan beberapa versi mayor akan mencantumkannya di sana, dan migrasi yang gagal dijalankan biasanya hanya memberi tahu Anda setelah sebagian skema telah diubah.
Catat apa yang sedang Anda jalankan sekarang, sebelum mengubah apa pun:
docker compose images
docker image inspect --format '{{index .RepoDigests 0}}' postgres:16.4docker compose images mencantumkan image dan tag yang digunakan setiap layanan saat ini. Digest adalah satu-satunya nilai yang menamai image secara tepat, karena tag dapat dipindahkan untuk menunjuk ke lokasi lain kapan saja.
Ambil cadangan dari bagian sebelumnya dan salin ke luar server. Lakukan ini juga untuk rilis patch. Peningkatan versi yang dianggap sepele adalah yang sering kali tidak dipersiapkan oleh pengguna.
Kemudian, kunci (pin) versi di dalam file compose, karena latest bukanlah sebuah versi:
services:
db:
image: postgres:16.4Dengan image: postgres:latest, docker compose pull akan mengambil apa pun yang ditunjuk oleh tag tersebut hari ini dan Anda tidak memiliki cara untuk mengetahui apa yang Anda jalankan kemarin. Tag yang dikunci mengubah peningkatan versi menjadi pengeditan satu baris yang dapat Anda baca di git diff dan dibatalkan dengan satu pengeditan lagi. Kunci image aplikasi dengan cara yang sama, dengan mengambil versi yang tepat dari halaman rilis proyek tersebut.
Tarik (pull) dan buat ulang:
docker compose pull
docker compose up -d --waitdocker compose up -d membandingkan file dengan kontainer yang sedang berjalan dan hanya membuat ulang layanan yang image atau konfigurasinya berubah. Perintah ini tidak menyentuh volume bernama, sehingga kontainer baru akan dimulai dengan data yang sudah ada. Itulah tujuan dari proses ini sekaligus risikonya, karena saat pertama kali versi baru dijalankan biasanya merupakan waktu di mana migrasi skema dilakukan.
Pantau prosesnya:
docker compose ps
docker compose logs -f --tail=100 appKontainer yang gagal akan menampilkan Exited (1) di kolom STATUS pada docker compose ps, dan alasannya terdapat pada baris terakhir log-nya. Error migrasi akan terlihat jelas di sana dan tidak terlihat di tempat lain. Setelah log stabil, masuklah ke aplikasi dan gunakan selama satu menit.
Jika docker compose pull berhenti dengan no space left on device, lapisan image lama biasanya menjadi penyebabnya, dan membersihkan image Docker yang tidak terpakai akan mengembalikan ruang penyimpanan tersebut. Lakukan pembersihan setelah peningkatan versi terbukti berhasil, bukan sebelumnya, karena lapisan lama itulah yang digunakan jika Anda perlu melakukan rollback dengan cepat.
Cara melakukan rollback saat upgrade gagal
Terdapat dua skenario dengan konsekuensi yang sangat berbeda. Jika versi baru tidak mengubah skema, rollback hanya memerlukan satu baris perintah: kembalikan tag lama ke dalam file compose dan jalankan docker compose up -d. Kontainer akan diganti, volume tetap berada di tempatnya, dan kode lama akan membaca data yang sebelumnya ia tulis.
Jika versi baru melakukan migrasi skema, kode lama tidak akan bisa lagi membacanya. Migrasi dirancang untuk berjalan maju, dan sebagian besar proyek tidak menyertakan skrip downgrade. Akibatnya, versi lama akan berjalan lalu gagal pada kueri pertama terhadap kolom yang telah diubah namanya atau dihapus, dengan error seperti ERROR: column "avatar_url" does not exist. Satu-satunya jalan kembali adalah dump yang Anda ambil sebelum melakukan pull: kembalikan tag lama, hapus volume database, buat ulang volume kosong, restore dump ke dalamnya, lalu jalankan. Tanpa dump tersebut, tidak ada cara untuk kembali, itulah alasan mengapa backup harus dilakukan sebelum pull.
Versi mayor Postgres adalah bentuk yang paling berisiko, dan sering mengejutkan karena kegagalan terjadi saat upgrade, bukan saat rollback. Format data di disk berubah pada setiap rilis mayor. Ubah postgres:16.4 menjadi postgres:17.2, jalankan docker compose up -d, maka server baru akan menolak untuk start:
FATAL: database files are incompatible with server
DETAIL: The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 17.2.Image tersebut tidak menjalankan pg_upgrade untuk Anda. Jalur yang didukung di dalam stack Compose adalah dump, ganti, restore: lakukan dump saat versi lama masih berjalan, docker compose down, hapus volume database, atur tag baru, docker compose create untuk direktori data kosong yang baru, jalankan database, restore dump, lalu jalankan sisanya. Simpan dump lama sampai versi mayor baru telah menangani trafik nyata selama satu hari. Upgrade minor di dalam satu versi mayor, misalnya 16.4 ke 16.9, tidak memerlukan langkah ini karena formatnya stabil di antara versi tersebut dan kontainer akan langsung berjalan.
Apakah snapshot VPS termasuk cadangan (backup)?
Snapshot adalah pelengkap cadangan, dan keduanya memiliki titik kegagalan yang berbeda. Snapshot menyalin seluruh disk di tingkat hypervisor, sehingga dapat mengembalikan seluruh mesin dalam hitungan menit, termasuk bagian yang lupa Anda cadangkan. Hal ini menjadikannya alat yang tepat untuk satu tugas spesifik: pembaruan merusak server dan Anda ingin mengembalikannya ke kondisi dua puluh menit yang lalu.
Snapshot adalah alat yang buruk untuk kebutuhan lainnya. Granularitasnya mencakup seluruh mesin, sehingga memulihkan satu tabel yang terhapus berarti harus merestorasi seluruh server di tempat lain dan mengambil tabel tersebut secara manual. Retensi biasanya singkat. Salinan ini umumnya tersimpan di akun penyedia yang sama dengan server, sehingga jika akun hilang, server beserta snapshot-nya akan ikut hilang. Selain itu, snapshot dari mesin yang sedang berjalan menangkap database di tengah proses penulisan, sehingga database akan melakukan pemulihan crash (crash recovery) saat pertama kali dijalankan dan transaksi yang sedang berlangsung akan hilang.
Gunakan keduanya. Snapshot adalah tombol "undo" untuk durasi pembaruan. Dump adalah salinan yang tetap ada meskipun akun terhapus. perbedaan snapshot dan backup menjelaskan kegagalan apa saja yang dapat diatasi oleh masing-masing metode. Direktori cadangan yang sama juga merupakan kunci yang mengubah memindahkan stack ke VPS baru menjadi tugas rutin, alih-alih membangun ulang dari ingatan.
Apa yang mungkin salah, dan apa yang akan Anda lihat
Flag volumes pada down. docker compose down -v menghapus volume bernama yang dideklarasikan dalam file, dan Compose mengonfirmasinya dengan baris yang bertuliskan Volume myapp_db_data Removed. Tidak ada cara untuk membatalkannya. Perintah docker compose down biasa tidak akan menyentuh volume tersebut. Ketik bentuk panjangnya, docker compose down --volumes, agar flag yang bersifat destruktif ini menjadi kata yang harus Anda tuliskan secara lengkap.
Dump tanpa magic string. pg_restore: error: did not find magic string in file header berarti file tersebut bukan sebuah arsip. Penyebab umumnya adalah -T yang hilang pada docker compose exec, karena dengan TTY yang terpasang, stream akan diterjemahkan saat menuju shell Anda dan dump biner tersebut tiba dalam keadaan rusak. Lakukan dump kembali dengan -T, lalu periksa lima byte pertama dengan head -c 5.
Password yang tidak mau berubah. FATAL: password authentication failed for user "appuser" setelah proses restore berarti .env dan direktori data berasal dari waktu yang berbeda. Image tersebut hanya menetapkan password saat membuat direktori data yang kosong, sehingga mengedit .env di kemudian hari tidak akan mengubah apa pun di dalam database. Lakukan restore dengan .env yang cocok, atau ubah password di dalam database dengan ALTER USER.
Volume kedua yang kosong. Docker membuat volume sesuai permintaan, jadi docker run -v myapp_upload:/data dengan s yang hilang akan menulis ke dalam volume kosong yang baru dan melaporkan keberhasilan. docker volume ls kemudian akan menampilkan kedua nama tersebut, di mana salah satunya tidak berisi apa pun. Salin nama volume dari docker volume ls alih-alih mengetiknya berdasarkan ingatan.
Restore yang diarahkan ke produksi. Menjalankan perintah restore di /srv/myapp alih-alih /srv/myapp-restore akan menimpa data langsung (live) dengan cadangan, dan perintah tersebut terlihat identik di kedua tempat. Periksa pwd sebelum setiap perintah restore, dan simpan direktori latihan di tempat terpisah.
FAQ
Apakah docker compose down menghapus data saya?
Tidak. docker compose down menghapus kontainer dan jaringan default, namun membiarkan named volume dan bind mount tetap ada. docker compose down -v menghapus named volume yang dideklarasikan dalam file Anda, dan tindakan tersebut bersifat permanen. Bind mount adalah direktori pada host, sehingga Compose tidak pernah menghapusnya. Jika Anda ingin menghentikan layanan selama proses backup tanpa mengubah hal lainnya, gunakan docker compose stop sebagai gantinya.
Bisakah saya menyalin direktori data Postgres alih-alih menjalankan pg_dump?
Hanya jika kontainer dihentikan. Saat server berjalan, file-filenya berubah secara dinamis dan hasil salinan dapat berisi data yang tidak konsisten sehingga tidak dapat dipulihkan. Salinan tingkat file juga terikat pada satu versi mayor Postgres, sehingga tidak akan berjalan pada versi yang berbeda. Hentikan kontainer, arsipkan volume, jalankan kembali kontainer, dan perlakukan hasil tersebut sebagai metode pembangunan ulang yang cepat, bukan sebagai satu-satunya backup Anda. Dump adalah salinan portabel yang digunakan untuk proses restore.
Bagaimana cara upgrade Postgres ke versi mayor baru di Compose?
Mengubah tag saja tidak cukup. Server baru akan menolak untuk start pada direktori data lama dan mencatat The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 17.2 di log. Jalankan pg_dump saat versi lama masih berjalan, kemudian jalankan docker compose down, hapus volume database, atur tag baru, jalankan docker compose create untuk membuat volume kosong yang baru, jalankan database, dan restore dump ke dalamnya. Simpan dump lama sampai versi baru telah menangani trafik nyata.
Seberapa sering backup harus dilakukan, dan berapa lama saya harus menyimpannya?
Sesuaikan interval dengan seberapa banyak pekerjaan yang sanggup Anda ulangi jika terjadi kegagalan. Backup harian cukup untuk stack pribadi atau tim kecil, ditambah satu backup manual tambahan tepat sebelum melakukan upgrade apa pun. Untuk retensi, simpan riwayat yang cukup untuk mencakup kerusakan yang tidak segera Anda sadari, karena tabel yang rusak pada hari Jumat tidak dapat diperbaiki dengan salinan dari Kamis malam. restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune adalah kebijakan awal yang wajar. Apa pun jadwalnya, lakukan restore dari backup tersebut setiap tiga bulan sekali. Sebelum Anda melakukannya, Anda belum memiliki backup, Anda hanya memiliki file.
Apakah saya harus menghentikan seluruh stack untuk melakukan backup?
Biasanya tidak. Dump database tetap konsisten saat server berjalan, sehingga database tidak memerlukan downtime. Volume adalah masalah utamanya. Jika aplikasi hanya menambah file, seperti direktori unggahan, arsip langsung (live archive) sudah cukup aman. Jika aplikasi menulis ulang file di tempat, hentikan layanan tersebut selama proses penyalinan dengan docker compose stop app dan jalankan kembali setelahnya. Menghentikan aplikasi sementara database tetap berjalan biasanya merupakan durasi terpendek yang aman untuk dilakukan.