SSD Nodes Learn 🎉 VPS dari $5.50/bln
Panduan Matt ConnorOleh Matt Connor · Dikemas kini 2026-08-13

Pangkalan data dalam Docker atau hos: Mana lebih baik?

Menjalankan PostgreSQL, MySQL atau Redis dalam Docker adalah selamat untuk pengeluaran. Ketahui risiko sebenar berkaitan pengurusan volum, naik taraf versi dan had memori.

Patutkah pangkalan data dijalankan dalam Docker atau pada hos?

Jalankan pangkalan data dalam Docker. Bagi satu tindanan aplikasi pada satu VPS, penggunaan PostgreSQL, MySQL, MongoDB atau Redis dalam kontena merupakan pilihan pengeluaran yang biasa, dan perdebatan mengenainya biasanya tidak berasas. Kontena ialah proses Linux dengan namespace dan cgroup, bukannya mesin maya, jadi tiada hypervisor antara pangkalan data dan cakera. Dengan bind mount atau local named volume, operasi baca dan tulis akan terus ke sistem fail hos, sama seperti pemasangan melalui pakej.

Kos sebenar adalah dari segi operasi. Empat perkara menentukan sama ada persediaan ini baik atau akan membawa bencana: di mana data disimpan, siapa pemilik direktori tersebut, bagaimana proses naik taraf versi utama dilakukan, dan sama ada anda pernah memulihkan sandaran. Jika perkara ini diurus dengan betul, kontena hanyalah perincian teknikal. Jika diurus dengan salah, kontena akan menjadi punca masalah yang anda salahkan.

Keputusan ini adalah sama bagi setiap pangkalan data pelayan. Contoh di bawah menggunakan PostgreSQL, MySQL, MongoDB dan Redis, dan perbezaan khusus produk dinyatakan di mana ia relevan.

Perkara yang sebenarnya berubah dalam container

Bukan laluan storan, selagi anda melakukan mount. Kernel yang sama, page cache yang sama, sistem fail yang sama.

Terdapat satu perangkap prestasi yang nyata, iaitu apabila anda tidak melakukan mount apa-apa. Tanpa volume, direktori data akan masuk ke dalam lapisan boleh tulis (writable layer) container, iaitu sistem fail overlay yang disusun di atas imej. Penulisan di situ lebih perlahan, dan keseluruhan lapisan tersebut dipadamkan apabila container dibuang. Itulah punca masalah "pangkalan data saya kosong pagi ini".

Perkara yang benar-benar berubah:

  • Kitaran hayat. docker compose down memusnahkan container. Apa-apa yang tidak berada dalam volume akan hilang bersamanya.
  • Versi. Tag imej ialah versinya. Tiada apt upgrade di dalam container pangkalan data yang akan kekal selepas docker compose pull yang seterusnya.
  • Perakaunan memori. Had cgroup ialah sekatan keras yang dikuatkuasakan oleh kernel, dan pangkalan data tidak mengetahui kewujudannya.
  • Pengguna. Proses berjalan sebagai id pengguna berangka di dalam container, yang mungkin tidak memiliki apa-apa pada hos anda.

Lokasi data menentukan segala-galanya

Terdapat dua pilihan yang baik dan satu kesilapan yang lazim.

  • Volume bernama: pgdata:/var/lib/postgresql/data. Docker mencipta direktori di /var/lib/docker/volumes/<project>_pgdata/_data, dan entrypoint imej menetapkan pemilikan pada pelaksanaan pertama. Ini adalah jawapan lalai.
  • Bind mount: /srv/appname/pg:/var/lib/postgresql/data. Anda memilih laluan tersebut, jadi anda bertanggungjawab terhadap masalah keizinan.
  • Tiada mount langsung. Lihat di atas. Data berada di dalam kontena.

Pertukaran penuh (trade-off) adalah topik tersendiri, dan bind mount berbanding volume bernama meliputinya. Bagi pangkalan data, versi ringkasnya ialah: gunakan volume bernama kecuali anda mempunyai sebab khusus untuk mengetahui laluan hos, dan jika anda menggunakan bind mount, letakkannya di lokasi yang stabil seperti /srv/appname/pg dan bukannya di dalam direktori projek di mana git clean boleh mencapainya.

Satu had mutlak: jangan letakkan direktori data pangkalan data pada NFS (network file system) atau mana-mana mount rangkaian yang gelagat penguncian dan fsync-nya belum anda uji. Pangkalan data mengandaikan bahawa fsync yang berjaya bermaksud bait tersebut berada pada storan stabil. Apabila andaian itu salah, anda akan mendapat kerosakan data yang hanya kelihatan beberapa minggu kemudian.

Tetapkan nama volum sebelum volum hilang

Compose menamakan volum sebagai <project>_<volume>, dan nama projek ditetapkan secara lalai kepada nama direktori. Oleh itu, identiti volum bergantung pada nama direktori, iaitu sesuatu yang sering diubah oleh pengguna tanpa disedari.

Alihkan /srv/app ke /srv/app-old, atau namakan semula kunci pgdata dalam fail compose, dan docker compose up -d seterusnya akan mencipta volum kosong yang baharu. Postgres akan memulakan kluster segar di dalamnya. Kontena tersebut sihat, aplikasi bermula, dan semua jadual hilang. Berita baiknya, volum lama masih berada pada cakera di bawah nama yang lama.

docker volume ls
docker volume inspect app_pgdata

Tetapkan nama secara eksplisit supaya perkara ini tidak berlaku. Tentukan nama projek dan nama volum secara jelas:

name: myapp

services:
  db:
    image: postgres:17
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:
    name: myapp_pgdata

Jika volum terbiar sudah menyimpan data anda, salin data tersebut dengan pangkalan data dihentikan:

docker compose stop db
docker run --rm -v app_pgdata:/from -v myapp_pgdata:/to alpine sh -c 'cp -a /from/. /to/'
docker compose start db

Menyalin data semasa pangkalan data sedang berjalan akan menyebabkan salinan fail yang tidak lengkap kerana fail tersebut sedang ditulis. Hentikan pangkalan data terlebih dahulu.

Siapa pemilik direktori data

Imej rasmi Postgres, MySQL dan MongoDB menjalankan pelayan mereka sebagai ID pengguna tanpa keistimewaan, biasanya 999. Apabila kontena bermula sebagai root, entrypoint akan menukar pemilikan direktori data kepada pengguna tersebut dan kemudian menggugurkan keistimewaan. Itulah sebabnya bind mount yang kosong biasanya berfungsi pada percubaan pertama.

Ia gagal sebaik sahaja anda menetapkan user: dalam fail compose, kerana entrypoint tidak lagi mempunyai keistimewaan untuk membetulkan apa-apa. Postgres menyatakan perkara ini secara langsung:

initdb: error: could not change permissions of directory "/var/lib/postgresql/data": Operation not permitted

Direktori data yang wujud dengan mod yang salah akan memberikan mesej yang berbeza, dan mesej ini perlu dikenali kerana pembetulannya ialah chmod, bukan chown:

FATAL:  data directory "/var/lib/postgresql/data" has invalid permissions
DETAIL:  Permissions should be u=rwx (0700) or u=rwx,g=rx (0750).

MongoDB pada bind mount yang dimiliki oleh root gagal pada fail kunci (lock file):

Unable to create/open the lock file: /data/db/mongod.lock (Permission denied). Ensure the user executing mongod is the owner of the lock file and has the appropriate permissions.

Pembetulannya adalah dengan menjalankan chown pada direktori hos kepada ID berangka, bukan kepada nama:

sudo chown -R 999:999 /srv/appname/pg
sudo chmod 700 /srv/appname/pg
ls -ldn /srv/appname/pg

ls -ldn mencetak nombor dan bukannya nama, dan ia sepatutnya menunjukkan 999 999. Akaun yang dipanggil postgres pada hos anda dan akaun yang dipanggil postgres di dalam imej tidak mempunyai kaitan: kernel membandingkan nombor, dan nama dicari secara berasingan pada setiap sisi. bagaimana PUID dan PGID memetakan pengguna hos ke dalam kontena menerangkan pemetaan tersebut dengan betul. Di bawah Docker tanpa root atau pemetaan semula ruang nama pengguna (user namespace remapping), nombor tersebut akan berubah lagi, jadi baca ID daripada kontena yang sedang berjalan dan jangan sekadar menganggap ia 999.

Named volumes menjadikan keseluruhan bahagian ini tidak relevan pada pelaksanaan pertama, kerana Docker mencipta direktori kosong dan entrypoint memilikinya.

Naik taraf: naik taraf pakej berbanding perubahan tag imej

Pada hos, apt upgrade memindahkan anda sepanjang versi minor. Pengedaran anda tidak akan melompat ke versi major pangkalan data secara automatik, dan apabila anda memilih untuk melompat, kedua-dua set binari boleh dipasang serentak, yang merupakan perkara yang diperlukan oleh pg_upgrade.

Dalam kontena, tag ialah versi, jadi naik taraf hanyalah menyunting satu baris. Ini menjadikan naik taraf minor sesuatu yang remeh dan naik taraf major sebagai satu prosedur.

Tukar postgres:16 kepada postgres:17, jalankan docker compose up -d, dan kontena akan keluar serta-merta:

PostgreSQL Database directory appears to contain a database; Skipping initialization
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.

Tiada apa-apa yang rosak. Binari baharu enggan membaca susun atur katalog pada cakera yang lama, yang berubah antara versi major. Kembalikan tag kepada postgres:16 dan ia akan bermula semula. Rollback tersebut merupakan satu-satunya kelebihan naik taraf sebenar yang diberikan oleh kontena kepada anda.

Laluan yang disokong ialah dump dan restore. PostgreSQL lebih suka dump diambil oleh klien yang lebih baharu, jadi jalankannya daripada imej baharu terhadap pelayan lama yang masih berjalan pada rangkaian compose:

docker run --rm --network myapp_default -e PGPASSWORD="$POSTGRES_PASSWORD" \
  postgres:17 pg_dumpall -h db -U postgres > /srv/backups/all.sql
ls -lh /srv/backups/all.sql
tail -n 2 /srv/backups/all.sql

Fail tersebut sepatutnya bersaiz sekurang-kurangnya puluhan kilobait dan berakhir dengan baris yang berbunyi PostgreSQL database cluster dump complete. Fail yang bersaiz beberapa ratus bait bermakna dump gagal dan anda hampir memadamkan volum tanpa sebab. Hanya selepas pemeriksaan itu:

docker compose down
docker volume rm myapp_pgdata
# edit the compose file: image: postgres:17
docker compose up -d db
docker compose exec -T db psql -U postgres -f /dev/stdin < /srv/backups/all.sql

Enjin lain berbeza:

  • MySQL 8 menaik taraf kamus datanya sendiri semasa permulaan, jadi perubahan tag minor biasanya hanyalah satu but semula (restart). Baca nota keluaran sebelum melompat antara siri keluaran, dan ambil dump terlebih dahulu walau apa pun keadaannya.
  • MariaDB menjangkakan mariadb-upgrade dijalankan selepas pelayan naik pada versi baharu.
  • MongoDB mesti dinaik taraf satu versi major pada satu masa, dan selepas setiap langkah anda menetapkan versi keserasian ciri sebelum meneruskan. Melangkau versi bermakna mongod enggan bermula dan mencatat baris UPGRADE PROBLEM yang menamakan featureCompatibilityVersion. Dari MongoDB 7.0 dan seterusnya, arahan tersebut memerlukan flag pengesahan eksplisit: db.adminCommand({ setFeatureCompatibilityVersion: "8.0", confirm: true }).
  • Redis memuatkan fail snapshot lama dengan lancar tetapi tidak yang lebih baharu, jadi naik taraf hanyalah satu but semula dan turun taraf (downgrade) boleh gagal memuatkan data.

Peraturan umum: kontena menjadikan turun taraf mudah dan tidak menjadikan naik taraf lebih mudah.

Mengapa kontena pangkalan data saya berhenti dengan kod 137?

Ini kerana ia ditamatkan oleh OOM (out of memory) killer kernel. 137 adalah hasil daripada 128 ditambah dengan signal 9.

docker compose ps
docker inspect myapp-db-1 | grep -i oomkilled
journalctl -k | tail -n 20

docker compose ps menunjukkan Exited (137), baris inspect membaca "OOMKilled": true, dan log kernel mengandungi entri yang sepadan:

Memory cgroup out of memory: Killed process 4711 (postgres) total-vm:2170416kB

Berikut adalah mekanismenya, dan ia sering mengejutkan pengguna. PostgreSQL dan MySQL menetapkan saiz penimbal (buffer) berdasarkan jumlah memori yang dilaporkan oleh hos. Had cgroup tidak mengubah angka tersebut bagi aplikasi berkenaan. Pada hos 16 GB dengan had 2 GB, pangkalan data merancang seolah-olah ia mempunyai 16 GB, dan cgroup akan menamatkannya jauh sebelum hos itu sendiri mengalami sebarang tekanan. Jadi, had memori sahaja tidak mencukupi. Anda juga mesti memberitahu pangkalan data tentang kapasiti sebenar yang ada:

  • PostgreSQL: tetapkan shared_buffers, dan beri perhatian kepada work_mem. work_mem diperuntukkan bagi setiap operasi isihan (sort) untuk setiap sambungan, jadi nilai yang terlalu besar didarab dengan lima puluh sambungan adalah punca biasa kontena mati semasa beban tinggi dan bukannya semasa permulaan.
  • MySQL dan MariaDB: tetapkan innodb_buffer_pool_size, yang secara lalainya ialah 128M. Biarkan innodb_dedicated_server dimatikan dalam kontena, kerana tugas utamanya adalah untuk menetapkan saiz sendiri berdasarkan memori mesin yang dikesan.
  • MongoDB: tetapkan saiz cache WiredTiger secara eksplisit dan jangan biarkan ia meneka berdasarkan memori hos.
  • Redis: maxmemory secara lalainya adalah tanpa had, jadi Redis akan berkembang sehingga cgroup menghentikannya. Tetapkan maxmemory pada tahap yang selesa di bawah had kontena dan pilih maxmemory-policy yang sesuai.

Postgres juga melaporkan peristiwa ini dari pihaknya sendiri, dan pasangan baris ini adalah apa yang akan anda temui dalam log:

LOG:  server process (PID 123) was terminated by signal 9: Killed
LOG:  terminating any other active sessions due to crash of another server process

Satu backend yang ditamatkan akan memaksa setiap backend lain untuk dimulakan semula, kerana memori kongsi (shared memory) mungkin menjadi tidak konsisten. Ini menyebabkan ribut sambungan (connection storm) untuk aplikasi anda, bukannya peristiwa yang senyap. menetapkan had memori dalam Docker Compose merangkumi sintaks serta perbezaan antara mem_limit dan bentuk deploy.resources.

Tiada satu pun daripada masalah ini hilang pada hos. Ia hanya berpindah. Tanpa cgroup, pangkalan data akan bersaing dengan segala-galanya di dalam mesin tersebut, dan OOM killer hos akan memilih mangsa berdasarkan skor, yang mungkin termasuk sshd. Had yang menamatkan pangkalan data secara boleh jangka adalah lebih mudah untuk dikendalikan berbanding OOM hos yang boleh menyebabkan anda terkunci keluar.

Sandaran: lakukan dump di dalam, sandarkan di luar

Jangan sandarkan pangkalan data yang sedang berjalan dengan menyalin direktori datanya. Salinan peringkat fail yang diambil semasa pelayan sedang menulis akan menghasilkan salinan yang rosak (torn copy), dan anda hanya akan mengetahuinya semasa proses pemulihan.

Terdapat dua kaedah yang betul: lakukan dump menggunakan alat pangkalan data itu sendiri semasa ia berjalan dan sandarkan fail dump tersebut, atau hentikan kontena dan salin volum tersebut dalam keadaan sejuk (cold backup).

docker compose exec -T db pg_dump -U postgres -Fc appdb > /srv/backups/appdb.dump
docker compose exec -T db mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" --single-transaction --all-databases > /srv/backups/mysql.sql
docker compose exec -T db mongodump --archive --gzip --db appdb > /srv/backups/appdb.archive.gz
docker compose exec -T redis redis-cli BGSAVE

-T adalah penting. Tanpanya, docker compose exec boleh melampirkan terminal pada arahan tersebut, dan lapisan terminal akan menambah carriage return pada aliran output. Fail dump teks kemudiannya akan dipulihkan dengan ralat yang ganjil, manakala dump binari akan menjadi rosak. Ia gagal secara senyap semasa proses sandaran dan gagal dengan ketara sebulan kemudian.

--single-transaction memberikan mysqldump syot kilat (snapshot) jadual InnoDB yang konsisten tanpa mengunci keseluruhan pelayan.

Arahan-arahan tersebut hanya menulis satu fail setiap satu. Ia bukanlah satu sistem sandaran: tiada pengekalan (retention), tiada salinan di luar pelayan, dan tiada pengesahan. Serahkan direktori dump tersebut kepada alat yang melakukan ketiga-tiga perkara ini, iaitu tujuan utama sandaran restic daripada VPS. Sandarkan /srv/backups, bukan /var/lib/docker/volumes.

Kemudian, jalankan proses pemulihan, kerana sandaran yang tidak pernah anda pulihkan bukanlah satu sandaran:

docker compose exec -T db createdb -U postgres restore_test
docker compose exec -T db pg_restore -U postgres -d restore_test < /srv/backups/appdb.dump
docker compose exec -T db psql -U postgres -d restore_test -c '\dt'

\dt sepatutnya menyenaraikan jadual aplikasi anda. Hasil yang kosong, atau Did not find any relations., bermakna fail dump tersebut tidak seperti yang anda sangkakan. Gugurkan restore_test apabila anda selesai.

Perintah yang memadamkan segala-galanya

docker compose down -v.

Perintah down yang biasa akan memadamkan kontena dan rangkaian. Perintah -v pula akan memadamkan setiap volume bernama yang diisytiharkan dalam fail compose tersebut, serta setiap volume tanpa nama yang dipasang pada kontena berkenaan. Tiada gesaan pengesahan dan tiada cara untuk membatalkan tindakan ini. Ini merupakan cara paling lazim pangkalan data yang dihoskan sendiri musnah, dan ia biasanya berlaku semasa menyelesaikan masalah yang tidak berkaitan, kerana jawapan dalam forum menyarankan untuk menjalankannya.

Empat perkara dapat mengurangkan kesan kerosakan:

  • Isytiharkan volume pangkalan data sebagai external: true. Compose tidak akan memadamkan volume yang tidak dimilikinya, jadi -v tidak dapat mencapainya. Anda perlu menciptanya sekali sahaja menggunakan docker volume create myapp_pgdata.
  • Gunakan docker compose stop dan docker compose start untuk mulakan semula rutin. perbezaan down dengan stop dalam Compose menjelaskan perkara yang dipadamkan oleh setiap perintah tersebut.
  • Simpan fail dump pada laluan hos di luar setiap volume yang diuruskan oleh compose.
  • Jangan sesekali menampal -v daripada jawapan penyelesaian masalah ke dalam stack yang mengandungi data penting anda.

Jangan dedahkan port pangkalan data

Baris ini meletakkan pangkalan data anda pada internet awam:

    ports:
      - "5432:5432"

Ia mengikat pada setiap antara muka. Docker menerbitkan port dengan menulis semula destinasi paket sebelum peraturan input firewall anda melihatnya, dan peraturan ufw berada dalam rantaian input, jadi ufw deny 5432 tidak melakukan apa-apa langsung. mengapa port yang diterbitkan Docker memintas ufw menunjukkan lintasan rantaian tersebut.

Aplikasi dalam projek compose yang sama mencapai pangkalan data melalui nama servis pada rangkaian compose, jadi ia tidak memerlukan port yang diterbitkan. Padamkan blok tersebut. Jika anda mahukan klien pada hos, ikat pada loopback sahaja:

    ports:
      - "127.0.0.1:5432:5432"

Semak apa yang sebenarnya sedang mendengar:

sudo ss -ltnp | grep 5432

127.0.0.1:5432 adalah apa yang anda mahukan. 0.0.0.0:5432 bermakna sesiapa sahaja boleh mencuba kata laluan anda.

Apa yang perlu dijalankan di mana

Satu aplikasi pada satu VPS. Kontena. Gunakan volume bernama dengan nama yang ditetapkan, tiada port yang diterbitkan, had memori dengan tetapan pangkalan data yang sepadan, dan dump harian ke laluan hos yang dikumpul oleh restic. Mulakan daripada pemasangan Docker yang bersih pada VPS dan simpan stack tersebut dalam satu fail compose yang anda commit. Kelebihannya nyata: versi pangkalan data menjadi baris yang boleh disemak dalam git.

Satu hos yang menjalankan beberapa servis. Kontena, satu pangkalan data bagi setiap aplikasi, bukan satu pelayan kongsi untuk kesemuanya. Pelayan kongsi menggandingkan setiap aplikasi kepada satu jadual naik taraf, dan satu pertanyaan (query) yang tidak terkawal akan menyebabkan gangguan kepada semua orang. Berikan setiap kontena had memorinya sendiri supaya pertanyaan yang bermasalah terhad kepada aplikasi yang menghasilkannya. Beberapa instans Postgres yang kecil menggunakan sedikit lebih banyak cakera tetapi memerlukan koordinasi yang jauh lebih rendah.

Pangkalan data adalah produknya. Jalankannya pada hos daripada repositori pakej vendor, atau bayar untuk perkhidmatan terurus. pg_upgrade memerlukan kedua-dua versi utama binari dipasang pada masa yang sama, yang disediakan oleh pakej tetapi tidak disediakan oleh imej versi tunggal. Replikasi dan pemulihan titik masa (point in time recovery) dengan pengarkiban WAL (write ahead log) adalah lebih mudah apabila pangkalan data menguasai mesin dan cakera tersebut. Pilih laluan yang membosankan untuk sistem yang akan menghantar notifikasi kepada anda pada pukul 03:00.

Aplikasi adalah kecil. Pertimbangkan untuk tidak menjalankan pangkalan data pelayan langsung. Aplikasi web penulis-tunggal pada satu VPS selalunya lebih baik dilayani oleh SQLite dalam pengeluaran pada VPS, di mana sandarannya adalah satu fail dan laluan naik tarafnya adalah versi pustaka.

FAQ

Adakah selamat untuk menjalankan pangkalan data pengeluaran dalam Docker?

Ya, untuk tindanan aplikasi pelayan tunggal. Kontena ialah proses Linux dengan namespace dan cgroup di sekelilingnya, jadi dengan volume yang dilekapkan, pangkalan data menulis ke dalam sistem fail hos yang sama seperti yang digunakan jika anda memasangnya daripada pakej. Risikonya lebih kepada aspek operasi berbanding kelajuan: volume yang namanya tidak ditetapkan (pinned), bind mount yang dimiliki oleh ID pengguna yang salah, pemulihan (restore) yang tidak pernah anda uji, dan docker compose down -v. Selesaikan empat perkara tersebut dan kontena itu akan berfungsi dengan baik. Beralih kepada pemasangan hos apabila pangkalan data menjadi beban kerja utama dan anda memerlukan pg_upgrade, replikasi atau pemulihan titik masa (point in time recovery).

Patutkah saya menggunakan bind mount atau named volume untuk data pangkalan data?

Gunakan named volume kecuali anda mempunyai sebab khusus untuk mengetahui laluan hos. Docker mencipta direktori tersebut dan entrypoint imej menetapkan pemilikan pada permulaan pertama, jadi masalah kebenaran (permission) tidak akan timbul. Tetapkan volume dengan name: yang eksplisit atau tandakannya sebagai external: true, jika tidak, menamakan semula direktori projek akan menghasilkan volume kosong yang baharu dan pangkalan data yang kosong secara senyap. Bind mount boleh digunakan jika anda melakukan chown pada direktori hos kepada ID pengguna berangka yang digunakan oleh imej tersebut, iaitu 999 untuk imej rasmi Postgres, MySQL dan MongoDB. Sahkan dengan ls -ldn, kerana ls -l menunjukkan nama hos anda untuk nombor tersebut dan nama itu tidak bermakna di dalam kontena.

Apakah yang dipadamkan oleh docker compose down -v?

Ia membuang kontena dan rangkaian seperti down biasa, dan -v pula membuang setiap named volume yang diisytiharkan dalam fail compose tersebut berserta setiap anonymous volume yang dilampirkan pada kontena berkenaan. Ini termasuk pangkalan data. Tiada gesaan pengesahan dan tiada pemulihan. Volume yang ditandakan sebagai external: true tidak akan dibuang, itulah sebab utama untuk menandakan volume pangkalan data sebagai external. Untuk mulakan semula rutin, gunakan docker compose stop dan docker compose start sebaliknya.

Bagaimanakah cara saya menaik taraf PostgreSQL kepada versi utama baharu dalam Docker?

Lakukan dump dan restore. Menukar postgres:16 kepada postgres:17 dan memulakan semula akan memberikan FATAL: database files are incompatible with server dengan baris DETAIL yang menamakan kedua-dua versi, kerana binari baharu tidak akan membaca susun atur katalog lama. Tiada apa-apa yang rosak: kembalikan tag lama dan ia akan bermula semula. Ambil pg_dumpall menggunakan klien versi baharu terhadap kontena lama yang sedang berjalan, sahkan fail berakhir dengan PostgreSQL database cluster dump complete, kemudian naikkan tag baharu pada volume kosong dan muatkan dump tersebut. Naik taraf kecil dalam satu versi utama hanya memerlukan pull dan mulakan semula.

Mengapakah kontena pangkalan data saya keluar dengan kod 137?

137 ialah 128 tambah isyarat 9, jadi sesuatu telah mematikan proses tersebut secara serta-merta. Jalankan docker inspect <container> | grep -i oomkilled; nilai true bermaksud kontena telah mencapai had memori cgroupnya. Punca biasa ialah PostgreSQL dan MySQL membaca jumlah memori daripada hos dan tidak melihat had kontena, jadi ia merancang untuk 16 GB walaupun berada dalam 2 GB. Tetapkan shared_buffers dan work_mem, atau innodb_buffer_pool_size, untuk memadankan had yang anda berikan kepada kontena. Semak journalctl -k untuk baris Memory cgroup out of memory yang sepadan bagi mengesahkan proses mana yang dipilih oleh kernel.