SSD Nodes Learn 🎉 VPS dari $5.50/bln
Panduan Matt ConnorOleh Matt Connor

Cara sandar dan naik taraf Docker Compose stack

Panduan lengkap sandaran Docker Compose termasuk dump pangkalan data, volume, dan fail konfigurasi. Ketahui langkah selamat untuk naik taraf tanpa risiko kehilangan data.

Perkara yang perlu terkandung dalam sandaran stack Docker Compose

Sandaran stack Docker Compose perlu mengandungi empat perkara berasingan, dan kehilangan mana-mana daripadanya bermakna aplikasi tidak dapat dipulihkan: fail compose, .env di sebelahnya, kandungan setiap volume, dan dump pangkalan data yang ditulis oleh klien pangkalan data itu sendiri. Menyalin fail pangkalan data semasa containernya sedang berjalan bukanlah satu sandaran. Naik taraf menggunakan senarai yang sama ditambah satu peraturan: ambil sandaran sebelum anda melakukan pull, kerana migrasi skema ditulis untuk berjalan ke hadapan dan kebanyakan projek tidak menyediakan cara untuk kembali ke versi asal.

Segala perkara di bawah mengandaikan stack sudah dideploy dan docker compose ps menunjukkan ia sedang berjalan. Contoh-contoh ini menggunakan direktori projek di /srv/myapp dengan servis bernama app dan db. Gantikan dengan nama anda sendiri. Perintah-perintah ini sengaja dikekalkan dalam bentuk generik, kerana bahagian yang penting, iaitu volume dan pangkalan data, berfungsi dengan cara yang sama tidak kira apa jua aplikasinya.

Tentukan perkara 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=myapp

docker compose config --volumes mencetak nama ringkas bagi volume bernama yang diisytiharkan oleh fail anda. docker volume ls mencetak nama sebenar yang dibawa oleh volume tersebut pada cakera. Kedua-dua senarai ini berbeza kerana Compose meletakkan nama projek di hadapan: volume yang ditulis sebagai db_data dalam fail wujud sebagai myapp_db_data. Nama projek secara lalai adalah nama direktori, jadi menamakan semula direktori akan menghalakan stack kepada set volume kosong yang baharu dan membiarkan volume lama kekal di situ dengan data anda. Setiap arahan di bawah memerlukan nama sebenar daripada docker volume ls.

Bind mount tidak muncul dalam kedua-dua senarai tersebut. Dalam fail compose, ia merupakan entri dengan laluan hos di sebelah kiri titik bertindih, ./config:/app/config. Ia adalah direktori biasa pada hos, jadi alatan biasa boleh mencapainya. Volume bernama terletak di bawah /var/lib/docker/volumes/, dan docker volume inspect --format '{{.Mountpoint}}' myapp_db_data mencetak laluan tepat bagi salah satu daripadanya. Jenis yang digunakan oleh stack anda mengubah cara anda menyalinnya, dan bind mount berbanding volume bernama merangkumi pertukaran tersebut sepenuhnya.

Sekarang, asingkan perkara yang anda temui kepada dua kumpulan. Sesetengah volume menyimpan keadaan yang tidak boleh dicipta semula: fail yang dimuat naik, kunci yang dijana, pangkalan data itu sendiri, dan apa-apa sahaja yang ditaip oleh pengguna ke dalam aplikasi. Kumpulan lain menyimpan data terbitan seperti imej kecil (thumbnail) dan indeks carian, yang dibina semula oleh aplikasi itu sendiri. Membuat sandaran bagi kumpulan kedua hanya membuang ruang cakera dan masa pemulihan serta tidak memberikan sebarang manfaat. Volume cache Redis adalah contoh paling jelas: kehilangannya hanya menyebabkan satu permintaan pertama yang perlahan.

Sandarkan fail compose dan fail .env

Kedua-dua fail ini terletak bersebelahan pada hos dan tiada satu pun yang berada di dalam mana-mana volum. .env menyimpan kata laluan pangkalan data, rahsia aplikasi dan sebarang token API, jadi fail inilah yang membolehkan himpunan volum berfungsi semula sebagai aplikasi. Fail ini juga biasanya disenaraikan dalam .gitignore, yang bermaksud pelan "konfigurasi saya ada dalam git" tidak merangkumi fail tunggal yang paling penting. Menyimpan rahsia dalam fail env ialah corak yang betul, dan ia meletakkan tanggungjawab yang sepadan pada sandaran 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/.env

Salin setiap fail compose yang digunakan oleh stack, bukan hanya fail yang pertama. Stack yang dimulakan dengan -f compose.yaml -f compose.prod.yaml memerlukan kedua-dua fail tersebut untuk kembali dengan cara yang sama, dan cara berbilang fail compose digabungkan menentukan nilai yang sebenarnya sampai ke kontena.

Satu amaran mengaitkan .env dengan volum. Imej rasmi Postgres membaca POSTGRES_PASSWORD hanya apabila ia memulakan direktori data yang kosong. Menukar nilai tersebut kemudian tidak akan menukar kata laluan di dalam pangkalan data. Pulihkan volum bulan lepas bersebelahan dengan .env hari ini dan aplikasi akan gagal bersambung dengan FATAL: password authentication failed for user "appuser", walaupun kedua-dua fail kelihatan betul semasa diperiksa. Pastikan .env dan volum daripada detik yang sama disimpan bersama dalam sandaran yang sama.

Dump pangkalan data menggunakan kliennya sendiri

Pelayan pangkalan data menulis ke failnya secara berterusan. tar bagi /var/lib/postgresql/data yang diambil semasa pelayan sedang berjalan menyalin beberapa halaman dari sebelum penulisan dan beberapa dari selepasnya, jadi arkib tersebut mengandungi campuran detik yang mungkin tidak boleh dimainkan semula. Alat dump membaca di dalam satu transaksi tunggal, jadi fail tersebut mengandungi satu detik yang konsisten. Perbezaan itulah yang memisahkan sandaran (backup) daripada salinan.

docker compose exec -T db sh -c \
  'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' \
  > /srv/backups/myapp/db-$(date +%F).dump

Kekalkan -T. Ia mematikan peruntukan TTY, dan dengan TTY yang dilampirkan, Docker menterjemahkan aliran output dalam perjalanannya ke shell anda, yang akan merosakkan dump binari. Anda tidak akan mengetahui perkara itu sehingga proses pemulihan gagal. Tanda petik tunggal juga penting: ia menghalang shell hos anda daripada mengembangkan $POSTGRES_USER, supaya shell di dalam kontena yang mengembangkannya, menggunakan nilai yang telah ditetapkan oleh fail compose di sana. -Fc menulis format tersuai, yang memampatkan data semasa ia berjalan dan membolehkan pg_restore memilih objek daripadanya kemudian.

Peranan (roles) dan kata laluan masing-masing berada di luar mana-mana pangkalan data tunggal, jadi ambilnya juga:

docker compose exec -T db sh -c 'pg_dumpall -U "$POSTGRES_USER" --globals-only' \
  > /srv/backups/myapp/globals.sql

Kemudian semak sama ada fail tersebut adalah dump dan bukannya mesej ralat:

ls -lh /srv/backups/myapp/
head -c 5 /srv/backups/myapp/db-$(date +%F).dump

Dump format tersuai bermula dengan lima bait PGDMP. Fail dengan sifar bait, atau yang bermula dengan pg_dump:, bermakna arahan tersebut gagal. Shell mencipta fail output sebelum arahan dijalankan, jadi dump yang gagal masih meninggalkan fail dengan nama yang munasabah dan cap masa yang munasabah. Itulah kegagalan sandaran senyap yang paling biasa berlaku.

Bagi MariaDB atau MySQL, klien berubah tetapi 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 bagi jadual InnoDB tanpa menyekat penulis. Pada imej MySQL, arahannya ialah mysqldump dan pemboleh ubahnya ialah MYSQL_ROOT_PASSWORD dan MYSQL_DATABASE. Pada imej MariaDB semasa, mysqldump masih berfungsi sebagai nama keserasian untuk mariadb-dump. Ambil perhatian bahawa kata laluan yang diberikan pada baris arahan boleh dilihat dalam senarai proses kontena selagi dump berjalan.

SQLite memerlukan penjagaan tersendiri. Pangkalan data tersebut adalah satu fail, tetapi transaksi terkini mungkin masih berada dalam fail -wal yang berasingan di sebelahnya, jadi menyalin .db sahaja akan menyebabkan pangkalan data anda kehilangan penulisan terbaharunya. Jika imej tersebut menyertakan klien, sqlite3 /data/app.db ".backup '/data/app-backup.db'" akan menulis salinan yang konsisten semasa aplikasi berjalan. Jika tidak, hentikan kontena dan salin fail .db bersama-sama dengan pasangan -wal dan -shm miliknya.

Jika pangkalan data anda berjalan pada hos dan bukannya di dalam stack, arahan yang sama terpakai tanpa awalan docker compose exec, dan menjalankan pangkalan data dalam Docker atau pada hos adalah wajar dibaca sebelum pembinaan semula anda yang seterusnya.

Menangkap volum

Volum bernama tidak mempunyai laluan hos yang perlu anda sunting secara manual, jadi lekapkan ia ke dalam kontena pakai buang dan arkibkan dari situ.

docker run --rm \
  -v myapp_uploads:/data:ro \
  -v /srv/backups/myapp:/backup \
  alpine:3 tar czf /backup/uploads.tar.gz -C /data .

Kontena pembantu melekapkan volum dalam mod baca sahaja pada /data dan direktori sandaran anda pada /backup, kemudian menulis arkib tersebut ke bahagian hos. --rm membuang pembantu tersebut sebaik sahaja tar tamat. :ro adalah penting, kerana arahan tar yang tersalah taip tidak akan merosakkan sumber. -C /data . adalah perkara yang memastikan pemulihan berlaku di tempat yang betul: ia menyimpan setiap laluan secara relatif kepada akar volum. Tulis tar czf /backup/uploads.tar.gz /data sebaliknya dan setiap laluan akan mendapat data/ di hadapan, jadi pemulihan akan mencipta /data/data di dalam volum dan aplikasi akan melihat direktori yang kosong. Arkib tersebut menjadi milik root, kerana tar dijalankan sebagai root di dalam kontena. Jalankan sudo chown "$USER" /srv/backups/myapp/uploads.tar.gz jika itu mengganggu anda, dan baca bagaimana PUID dan PGID menentukan pemilikan fail jika fail yang dipulihkan tidak boleh dibaca oleh aplikasi.

Jalankan ia sekali untuk setiap volum bernama. Bind mount tidak memerlukan kontena langsung: tar czf /srv/backups/myapp/config.tar.gz -C /srv/myapp/config . melakukan tugas yang sama pada hos.

Tentukan bagi setiap volum sama ada aplikasi perlu dihentikan. Tar secara langsung (live tar) bagi volum yang ditulis semula oleh aplikasi boleh menangkap fail di pertengahan proses penulisan. Bagi direktori muat naik, di mana fail ditulis sekali dan kemudian hanya dibaca, risiko itu adalah kecil. Bagi perkara lain, hentikan servis tersebut sepanjang tempoh penyalinan dengan docker compose stop app, kemudian docker compose start app. stop membiarkan kontena dan volum di tempatnya, yang merupakan perkara yang anda mahukan di sini, dan perbezaan antara down dan stop perlu dipastikan sebelum anda menaip salah satu daripadanya.

Jangan anggap tar bagi volum pangkalan data sebagai sandaran pangkalan data anda. Dump adalah sandarannya. Arkib volum bagi pangkalan data yang dihentikan hanyalah laluan bina semula pantas yang berguna dan tiada yang lain.

Urutan operasi

  1. Salin fail compose dan .env ke dalam direktori sandaran.
  2. Lakukan dump pangkalan data semasa ia masih berjalan.
  3. Hentikan kontena aplikasi jika volumnya berubah di tempat asal.
  4. Arkibkan setiap volum bernama dan setiap direktori bind-mount.
  5. Mulakan semula apa sahaja yang telah dihentikan, kemudian sahkan dengan docker compose ps.
  6. Catatkan tag imej dan digest yang sedang dijalankan oleh stack tersebut.
  7. Salin keseluruhan direktori sandaran keluar dari pelayan ini.

Langkah 7 adalah langkah yang sering ditangguhkan oleh pengguna.

Pindahkan salinan keluar dari pelayan

Sandaran yang disimpan pada cakera yang sama dengan timbunan aplikasi hanya melindungi anda daripada kesilapan sendiri, bukan perkara lain. Satu volum yang gagal, satu pelayan yang dipadamkan atau satu akaun yang hilang akan melenyapkan kedua-dua salinan serentak. Hantar direktori tersebut ke storan yang bukan VPS ini, mengikut jadual, dengan polisi pengekalan. sandaran restic daripada VPS merangkumi penyediaan repositori, flag pengekalan dan arahan semakan, jadi perkara tersebut tidak perlu diulang di sini.

restic juga boleh membaca dump terus daripada pipe, yang memastikan pangkalan data teks biasa tidak disimpan langsung pada cakera:

docker compose exec -T db sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' \
  | restic backup --stdin --stdin-filename db.dump

Walau apa pun alat yang anda gunakan, letakkan jadual tersebut dalam systemd timer atau cron job, dan pastikan tugasan tersebut melaporkan kegagalan ke tempat yang akan anda lihat. Skrip sandaran yang outputnya tidak ke mana-mana ialah skrip sandaran yang boleh berhenti berfungsi selama enam bulan tanpa disedari oleh sesiapa.

Buktikan sandaran berfungsi dengan latihan pemulihan

Sandaran yang tidak pernah dipulihkan hanyalah satu hipotesis. Latihan di bawah memulihkan data ke dalam tindanan (stack) kedua yang berjalan di sebelah tindanan pertama, supaya pengeluaran (production) terus beroperasi dan tiada apa yang anda taip boleh menjejaskannya.

Mekanismenya ialah nama projek. Compose mengambil nama tersebut daripada nama direktori dan melabelkannya pada setiap kontena serta volum yang dicipta. Salin sandaran ke dalam direktori baharu dan tindanan yang dipulihkan akan mendapat volumnya sendiri secara automatik.

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 .

Sunting fail compose yang disalin supaya port hos yang diterbitkan tidak bertembung dengan tindanan yang sedang berjalan, 18080:8080 sebagai ganti 8080:8080, atau tukar pemboleh ubah yang menetapkannya dalam .env yang disalin. Kemudian, cipta kontena dan volum kosongnya tanpa memulakan apa-apa:

docker compose create
docker volume ls --filter label=com.docker.compose.project=myapp-restore

Perintah kedua sepatutnya menyenaraikan nama volum yang sama seperti pengeluaran dengan myapp-restore_ di hadapan. Isikan volum tersebut, mulakan pangkalan data secara berasingan, dan muatkan 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 menggugurkan (drop) setiap objek sebelum menciptanya semula, yang menjadikan pemulihan boleh diulang. Tanpanya, percubaan kedua ke dalam pangkalan data yang sudah mengandungi jadual tersebut akan terhenti dengan pg_restore: error: could not execute query: ERROR: relation "users" already exists.

Kemudian, mulakan bahagian lain dan semak dengan cara pengguna melakukannya:

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=50

docker compose up -d --wait menyekat sehingga setiap servis melaporkan status berjalan atau sihat, dan keluar dengan kod bukan sifar jika ada yang gagal, inilah yang menjadikan langkah ini boleh diskripkan. Apabila servis tidak pernah menjadi sihat, docker compose ps menunjukkan statusnya, dan Semakan kesihatan Compose menjelaskan perkara yang dibaca oleh lajur tersebut. Kemudian, buka aplikasi pada port alternatif dan log masuk dengan akaun sebenar. Tulis satu rekod dan buka satu fail yang berada dalam volum. Pasangan itu adalah buktinya: dump telah dipulihkan, volum telah dipulihkan, dan kedua-duanya selaras antara satu sama lain. Latihan yang hanya membuktikan halaman log masuk terpapar tidak membuktikan apa-apa tentang data anda.

Hapuskan latihan tersebut sebaik sahaja ia lulus:

docker compose down -v

Ini adalah satu-satunya tempat di mana -v merupakan flag yang betul. Dalam direktori pengeluaran, perintah yang sama akan memadamkan volum yang anda cuba lindungi.

Cara menaik taraf stack Compose

Baca nota keluaran bagi setiap versi antara versi yang anda jalankan dengan versi yang anda inginkan, dan cari perkataan breaking serta migration. Projek yang tidak menyokong lompatan merentasi beberapa versi utama akan menyatakan perkara tersebut di situ, dan migrasi yang gagal dijalankan hanya akan memberitahu anda selepas ia mengubah sebahagian daripada skema.

Rekodkan apa yang anda jalankan sekarang, sebelum anda mengubah apa-apa:

docker compose images
docker image inspect --format '{{index .RepoDigests 0}}' postgres:16.4

docker compose images menyenaraikan imej dan tag yang digunakan oleh setiap servis pada masa ini. Digest adalah satu-satunya nilai yang menamakan imej dengan tepat, kerana tag boleh dialihkan untuk menunjuk ke tempat lain pada bila-bila masa.

Ambil sandaran daripada bahagian di atas dan salin keluar daripada pelayan. Lakukan ini untuk keluaran patch juga. Naik taraf yang murah adalah yang orang berhenti bersedia untuknya.

Kemudian, tetapkan versi dalam fail compose, kerana latest bukanlah satu versi:

services:
  db:
    image: postgres:16.4

Dengan image: postgres:latest, docker compose pull mengambil apa sahaja yang ditunjuk oleh tag tersebut pada hari ini dan anda tidak mempunyai cara untuk menamakan apa yang anda jalankan semalam. Tag yang ditetapkan menjadikan naik taraf sebagai suntingan satu baris yang boleh anda baca dalam git diff dan undurkan dengan satu lagi suntingan. Tetapkan imej aplikasi dengan cara yang sama, dengan mengambil versi tepat daripada halaman keluaran projek tersebut.

Tarik dan cipta semula:

docker compose pull
docker compose up -d --wait

docker compose up -d membandingkan fail tersebut dengan kontena yang sedang berjalan dan mencipta semula hanya servis yang imej atau konfigurasinya berubah. Ia tidak menyentuh named volumes, jadi kontena baharu bermula dengan data sedia ada. Itulah tujuan latihan ini dan juga risikonya, kerana permulaan pertama versi baharu biasanya adalah masa migrasi skema dijalankan.

Perhatikan prosesnya:

docker compose ps
docker compose logs -f --tail=100 app

Kontena yang gagal akan menunjukkan Exited (1) dalam lajur STATUS bagi docker compose ps, dan puncanya terdapat pada baris terakhir lognya. Ralat migrasi jelas kelihatan di situ dan tidak kelihatan di tempat lain. Apabila log menjadi stabil, log masuk dan gunakan aplikasi tersebut selama seminit.

Jika docker compose pull terhenti dengan no space left on device, lapisan imej lama biasanya menjadi puncanya, dan pembersihan imej Docker yang tidak digunakan akan mendapatkan semula ruang tersebut. Lakukan pembersihan selepas naik taraf terbukti berjaya, bukan sebelumnya, kerana lapisan lama itulah yang digunakan oleh rollback pantas.

Cara untuk membuat rollback apabila naik taraf gagal

Terdapat dua keadaan dan kosnya sangat berbeza. Jika versi baharu tidak mengubah skema, rollback hanya memerlukan satu baris: letakkan semula tag lama dalam fail compose dan jalankan docker compose up -d. Kontena digantikan, volum kekal di tempat asalnya, dan kod lama membaca data yang ditulisnya.

Jika versi baharu telah memigrasikan skema, kod lama tidak lagi boleh membacanya. Migrasi ditulis untuk berjalan ke hadapan, dan kebanyakan projek tidak menyertakan skrip penurunan taraf (downgrade), jadi versi lama akan bermula dan kemudian gagal pada pertanyaan pertama terhadap lajur yang telah dinamakan semula atau dibuang, dengan ralat berbentuk ERROR: column "avatar_url" does not exist. Jalan keluar adalah dengan menggunakan dump yang anda ambil sebelum melakukan pull: letakkan semula tag lama, alihkan volum pangkalan data, cipta semula volum kosong, pulihkan dump ke dalamnya, dan mulakan. Tanpa dump tersebut, tiada jalan keluar langsung, itulah sebab utama sandaran (backup) perlu dilakukan sebelum pull.

Versi utama Postgres adalah bentuk yang paling kritikal bagi perkara ini, dan ia mengejutkan pengguna kerana kegagalan berlaku semasa naik taraf dan bukannya semasa rollback. Format pada cakera berubah dengan setiap keluaran utama. Tukar postgres:16.4 kepada postgres:17.2, jalankan docker compose up -d, dan pelayan baharu enggan bermula:

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.

Imej tersebut tidak menjalankan pg_upgrade untuk anda. Laluan yang disokong di dalam stack Compose ialah dump, ganti, pulihkan: buat dump semasa versi lama masih berjalan, docker compose down, alih keluar volum pangkalan data, tetapkan tag baharu, docker compose create untuk direktori data kosong yang baharu, mulakan pangkalan data, pulihkan dump, dan mulakan bahagian yang lain. Simpan dump lama sehingga versi utama baharu telah mengendalikan trafik sebenar selama sehari. Naik taraf kecil di dalam satu versi utama, contohnya 16.4 ke 16.9, tidak memerlukan semua ini, kerana formatnya stabil merentasi versi tersebut dan kontena akan terus bermula.

Adakah snapshot VPS dianggap sebagai sandaran (backup)?

Ia merupakan pelengkap kepada sandaran, dan kedua-duanya mempunyai titik kegagalan yang berbeza. Snapshot menyalin keseluruhan cakera pada peringkat hypervisor, jadi ia memulihkan keseluruhan mesin dalam masa beberapa minit, termasuk bahagian yang anda terlupa untuk sandarkan. Ini menjadikannya alat yang tepat untuk satu tugas khusus: naik taraf (upgrade) merosakkan pelayan dan anda mahu mengembalikannya kepada keadaan dua puluh minit yang lalu.

Ia merupakan alat yang kurang sesuai untuk tujuan lain. Tahap perinciannya adalah keseluruhan mesin, jadi untuk memulihkan satu jadual (table) yang dipadamkan, anda perlu memulihkan keseluruhan pelayan di tempat lain dan mencari jadual tersebut daripadanya. Tempoh pengekalan biasanya singkat. Salinan tersebut biasanya disimpan dalam akaun penyedia yang sama dengan pelayan, jadi jika akaun hilang, pelayan dan snapshotnya akan hilang serentak. Selain itu, snapshot bagi mesin yang sedang berjalan akan menangkap pangkalan data semasa proses penulisan, jadi pangkalan data akan melakukan pemulihan ranap (crash recovery) pada permulaan pertama dan sebarang transaksi yang sedang diproses akan hilang.

Gunakan kedua-duanya. Snapshot ialah butang "undo" untuk tempoh naik taraf. Fail dump ialah salinan yang terselamat sekiranya akaun dipadamkan. perbezaan antara snapshot dan sandaran menghuraikan kegagalan yang dilindungi oleh setiap satunya. Direktori sandaran yang sama juga merupakan perkara yang menjadikan memindahkan stack ke VPS baharu sebagai tugas rutin dan bukannya proses membina semula daripada ingatan.

Perkara yang tidak kena, dan apa yang akan anda lihat

Bendera volumes pada down. docker compose down -v memadamkan volume bernama yang diisytiharkan dalam fail, dan Compose mengesahkannya dengan baris yang berbunyi Volume myapp_db_data Removed. Tiada cara untuk membatalkannya. docker compose down biasa membiarkannya tidak terusik. Taip bentuk panjang, docker compose down --volumes, supaya bendera yang bersifat merosakkan itu merupakan perkataan yang perlu anda eja sepenuhnya.

Dump tanpa rentetan ajaib. pg_restore: error: did not find magic string in file header bermaksud fail tersebut bukan arkib. Punca biasa ialah -T yang tiada pada docker compose exec, kerana dengan TTY yang dilampirkan, aliran tersebut diterjemahkan semasa dalam perjalanan ke shell anda dan dump binari tiba dalam keadaan rosak. Ambil semula dump dengan -T, kemudian semak lima bait pertama dengan head -c 5.

Kata laluan yang tidak mahu berubah. FATAL: password authentication failed for user "appuser" selepas pemulihan bermaksud .env dan direktori data datang daripada masa yang berbeza. Imej tersebut menetapkan kata laluan itu hanya apabila ia mencipta direktori data yang kosong, jadi menyunting .env kemudian tidak mengubah apa-apa di dalam pangkalan data. Pulihkan .env yang sepadan, atau tukar kata laluan di dalam pangkalan data dengan ALTER USER.

Volume kedua yang kosong. Docker mencipta volume atas permintaan, jadi docker run -v myapp_upload:/data dengan s yang tiada akan menulis ke dalam volume kosong yang baharu dan melaporkan kejayaan. docker volume ls kemudian menunjukkan kedua-dua nama, salah satu daripadanya tidak mengandungi apa-apa. Salin nama volume daripada docker volume ls daripada menaipnya berdasarkan ingatan.

Pemulihan yang disasarkan pada pengeluaran. Menjalankan arahan pemulihan dalam /srv/myapp dan bukannya /srv/myapp-restore akan menulis ganti data langsung dengan sandaran, dan arahan tersebut kelihatan serupa di kedua-dua tempat. Semak pwd sebelum setiap arahan pemulihan, dan simpan latihan tersebut dalam direktorinya sendiri.

FAQ

Adakah docker compose down memadamkan data saya?

Tidak. docker compose down membuang kontena dan rangkaian lalai, tetapi ia membiarkan named volumes dan bind mounts tidak terusik. docker compose down -v membuang named volumes yang diisytiharkan dalam fail anda, dan tindakan itu adalah kekal. Bind mounts adalah direktori pada hos, jadi Compose tidak akan membuangnya. Jika anda mahu servis dihentikan semasa sandaran dilakukan tanpa mengubah apa-apa yang lain, gunakan docker compose stop sebagai ganti.

Bolehkah saya menyalin direktori data Postgres dan bukannya menjalankan pg_dump?

Hanya jika kontena dihentikan. Semasa pelayan berjalan, failnya berubah secara berterusan dan salinan tersebut mungkin mengandungi data yang tidak konsisten yang tidak boleh dipulihkan. Salinan pada peringkat fail juga terikat kepada satu versi utama Postgres, jadi ia tidak akan bermula di bawah versi yang berbeza. Hentikan kontena, arkibkan volum, mulakan semula, dan anggap hasil tersebut sebagai laluan bina semula pantas dan bukannya satu-satunya sandaran anda. Fail dump adalah salinan mudah alih, dan ia adalah fail yang anda gunakan untuk pemulihan.

Bagaimanakah cara saya menaik taraf Postgres kepada versi utama baharu dalam Compose?

Menukar tag sahaja tidak mencukupi. Pelayan baharu akan enggan bermula pada direktori data lama dan mencatatkan The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 17.2 dalam log. Jalankan pg_dump semasa versi lama masih berjalan, kemudian docker compose down, buang volum pangkalan data, tetapkan tag baharu, jalankan docker compose create untuk mendapatkan volum kosong yang baharu, mulakan pangkalan data, dan pulihkan fail dump ke dalamnya. Simpan fail dump lama sehingga versi baharu telah mengendalikan trafik sebenar.

Berapa kerap sandaran perlu dijalankan, dan berapa lama saya perlu menyimpannya?

Sesuaikan selang masa dengan jumlah kerja yang anda sanggup lakukan semula. Sandaran harian sesuai untuk stack peribadi atau pasukan kecil, ditambah satu sandaran manual tambahan sejurus sebelum sebarang naik taraf. Untuk tempoh penyimpanan, simpan sejarah yang mencukupi untuk menampung kerosakan yang tidak disedari dengan segera, kerana jadual yang rosak yang ditemui pada hari Jumaat tidak dapat dibantu oleh salinan malam Khamis. restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune adalah polisi permulaan yang munasabah. Walau apa pun jadualnya, lakukan pemulihan daripadanya sekali setiap suku tahun. Selagi anda belum melakukannya, anda tidak mempunyai sandaran, anda hanya mempunyai fail.

Adakah saya perlu menghentikan keseluruhan stack untuk membuat sandaran?

Biasanya tidak. Fail dump pangkalan data adalah konsisten semasa pelayan berjalan, jadi pangkalan data tidak memerlukan downtime. Volum adalah persoalan sebenar. Jika aplikasi hanya menambah fail, seperti direktori muat naik, arkib secara langsung (live) adalah cukup selamat. Jika ia menulis semula fail di tempatnya, hentikan servis tersebut sepanjang tempoh penyalinan dengan docker compose stop app dan mulakan semula selepas itu. Menghentikan aplikasi sementara pangkalan data terus berjalan biasanya merupakan tempoh masa selamat yang paling singkat yang boleh anda aturkan.