Cara Pasang Docker Compose di Ubuntu 24.04 VPS
Ketahui cara pasang Docker Engine dan Compose v2 pada Ubuntu 24.04. Panduan ini merangkumi konfigurasi fail compose.yml, isu port ufw, dan cara sandaran data yang selamat.
Apa yang anda sedang bina
Docker Compose merupakan substrat bagi hampir semua perkara lain di laman ini. Nextcloud, Vaultwarden, n8n, Immich, Rocket.Chat, setiap panduan tersebut bermula dengan "tulis fail compose ini", dan halaman ini menjelaskan maksud sebenar fail tersebut. Anda akan memasang Docker Engine dan pemalam Compose v2 daripada repositori apt rasmi Docker pada Ubuntu 24.04, kemudian menyediakan stack dua servis yang sebenar, iaitu Miniflux, pembaca RSS yang ringan, berserta PostgreSQL, kerana pasangan ini menguji setiap corak yang digunakan oleh aplikasi yang lebih besar: imej yang dipin (pinned), pangkalan data dengan healthcheck, named volume, rahsia dalam fail .env, dan port yang diterbitkan hanya kepada localhost.
Pemasangan mengambil masa lima minit. Bahagian selebihnya dalam panduan ini merangkumi perkara yang akan menyusahkan kemudian hari: kumpulan docker yang merupakan root dengan nama lain, port yang diterbitkan yang memintas peraturan ufw anda secara terus, dan satu flag pada docker compose down yang memadamkan pangkalan data anda tanpa sebarang gesaan pengesahan.
Prasyarat: VPS KVM Ubuntu 24.04 yang baharu, pengguna dengan sudo, dan RAM sebesar satu gigabait atau lebih. Pemasangan Docker sedia ada juga boleh digunakan, bahagian pertama merangkumi perkara yang perlu dibuang.
Pasang daripada repositori Docker, bukan Ubuntu
Terdapat dua kesilapan yang perlu dielakkan sebelum menjalankan arahan pertama. Pakej docker.io milik Ubuntu memang berfungsi, tetapi ia ketinggalan berbanding keluaran Docker dan tidak mempunyai susun atur pemalam (plugin) yang diperlukan oleh aplikasi lain. Selain itu, binari docker-compose yang berdiri sendiri (yang mempunyai tanda sempang) ialah Compose v1: berasaskan Python, telah tamat tempoh hayat sejak 2023, dan merupakan punca tutorial lama tidak lagi berfungsi. Compose hari ini ialah docker compose dengan ruang, iaitu pemalam CLI yang dipasang daripada repositori yang sama dengan enjin Docker.
Jika mana-mana perisian tersebut sudah ada pada pelayan, buang dahulu, termasuk docker-compose-v2 iaitu pakej pemalam daripada Ubuntu, supaya semua komponen datang daripada satu repositori:
sudo apt remove -y docker.io docker-compose docker-compose-v2 docker-doc podman-docker containerd runcPackage 'docker.io' is not installed, so not removed adalah output biasa pada VPS yang baharu. Kemudian, tambah repositori Docker dan pasang:
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginSahkan ketiga-tiga lapisan tersebut:
docker --version
docker compose version
sudo docker run --rm hello-worldDua arahan pertama akan memaparkan rentetan versi, dan Docker Compose version v2.x.x mengesahkan anda mempunyai pemalam tersebut, bukannya binari v1 yang sudah tidak disokong. Arahan hello-world sepatutnya berakhir dengan Hello from Docker!. Pakej ini mendayakan servis semasa but; systemctl is-enabled docker akan memaparkan enabled.
Kumpulan docker adalah root, buat keputusan dengan sedar
Pada masa ini, setiap arahan docker memerlukan sudo, kerana soket daemon di /var/run/docker.sock dimiliki oleh root dan kumpulan docker. Tanpa keahlian, anda akan mendapat ralat Docker yang paling kerap dicari di Google:
permission denied while trying to connect to the Docker daemon socket at
unix:///var/run/docker.sockPenyelesaian standard:
sudo usermod -aG docker $USERKeahlian kumpulan berkuat kuasa semasa log masuk, jadi ralat tersebut akan kekal dalam shell semasa anda. Jalankan newgrp docker untuk sesi ini, atau log keluar dan log masuk semula; id sepatutnya menyenaraikan docker dalam kumpulan anda.
Sekarang bahagian yang jujur, dinyatakan secara jelas: keahlian kumpulan docker adalah root pada hos. Bukan "seakan-akan root", bukan "ditingkatkan", tetapi root. Sesiapa sahaja dalam kumpulan itu boleh menjalankan docker run --rm -it -v /:/host alpine chroot /host dan menguasai keseluruhan sistem fail, tanpa diminta kata laluan. Kumpulan ini wujud untuk kemudahan, bukan untuk pengasingan.
Mod rootless Docker adalah alternatif sebenar, daemon itu sendiri berjalan sebagai pengguna tanpa keistimewaan anda. Ia mempunyai kos: port di bawah 1024 memerlukan tetapan tambahan, rangkaian berjalan melalui shim ruang pengguna dengan overhead yang boleh diukur, dan sesetengah imej tidak berfungsi dengan betul tanpa root sebenar. Pada VPS pentadbir tunggal di mana satu-satunya log masuk sudah memegang sudo, perubahan kumpulan tidak mengubah apa-apa secara praktikal, dan ia adalah apa yang diandaikan oleh setiap panduan di sini, cuma jangan sekali-kali memberikannya seolah-olah ia kurang daripada sudo.
Anatomi fail compose
Berikan setiap stack direktori sendiri. Nama direktori menjadi nama projek, yang menjadi awalan bagi container, rangkaian dan volum:
sudo mkdir -p /opt/miniflux && sudo chown $USER /opt/miniflux && cd /opt/minifluxCiptakan compose.yml (nama moden; docker-compose.yml masih berfungsi). Abaikan kunci version: yang lama, ia sudah usang dan Compose akan memberi amaran jika ia menemuinya.
services:
miniflux:
image: miniflux/miniflux:2.2.9
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
environment:
- DATABASE_URL=postgres://miniflux:${POSTGRES_PASSWORD}@db/miniflux?sslmode=disable
- RUN_MIGRATIONS=1
- CREATE_ADMIN=1
- ADMIN_USERNAME=admin
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
- POSTGRES_USER=miniflux
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=miniflux
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "miniflux", "-d", "miniflux"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-data:Setiap baris di atas adalah satu keputusan. Lakukan satu demi satu.
Kunci versi imej, :latest berserta pull ialah naik taraf tanpa pengawasan
postgres:16-alpine, bukan postgres:latest. Tag tidak bersifat tetap: :latest akan menyemak semula kepada apa sahaja yang penyenggara (maintainer) muat naik paling baharu, setiap kali anda melakukan pull. Gabungkan itu dengan tabiat naik taraf rutin yang bakal anda pelajari, docker compose pull && docker compose up -d, dan :latest bermakna lompatan versi utama akan berlaku apabila pihak hulu (upstream) melancarkannya, bukan apabila anda memilihnya. Dengan PostgreSQL, ini bukan hipotesis: lompatan mengejut daripada 16 ke 17 menyebabkan container terperangkap dalam gelung ranap (crash-loop) pada direktori data yang tidak serasi, kerana naik taraf versi utama Postgres memerlukan proses dump dan restore, bukan sekadar but semula.
Kunci sekurang-kurangnya versi utama (postgres:16-alpine mengikuti keluaran patch 16.x), dan kunci aplikasi kepada keluaran tepat seperti miniflux/miniflux:2.2.9. Semak halaman keluaran projek tersebut dan gunakan apa sahaja yang terkini semasa anda menulis fail itu. Naik taraf kemudiannya menjadi suntingan satu baris yang anda lakukan dengan sengaja, yang boleh dilihat dalam git diff.
Terbitkan ke 127.0.0.1, kerana Docker memintas ufw
"127.0.0.1:8080:8080", alamat hos, port hos, port container. Kebanyakan tutorial menulis "8080:8080", yang merupakan singkatan bagi 0.0.0.0:8080:8080: mendengar pada setiap antara muka, termasuk yang awam.
Ini perangkapnya, dan hampir semua orang pernah terkena. Docker menerbitkan port dengan menulis peraturan DNAT yang menulis semula destinasi paket kepada IP dalaman container sebelum penapisan, jadi paket tersebut mengambil laluan FORWARD dan tidak pernah menyentuh INPUT, tempat peraturan ufw anda berada. sudo ufw deny 8080 melaporkan kejayaan, ufw status menunjukkan port dinafikan, namun servis masih menjawab seluruh internet. Firewall anda tidak rosak; ia dipintas secara sengaja oleh reka bentuk. Mengapa Docker memintas ufw, dan cara menapis trafik container dengan sebenar membincangkan mekanisme ini dan penyelesaian DOCKER-USER untuk port yang mesti kekal awam.
Tabiat yang menghilangkan masalah ini sepenuhnya: ikat (bind) port yang diterbitkan ke 127.0.0.1 melainkan anda mempunyai sebab khusus untuk tidak berbuat demikian, dan letakkan reverse proxy di hadapan untuk apa sahaja yang perlu menghadap dunia luar. Itulah yang dibina oleh panduan reverse proxy Traefik sebagai langkah seterusnya selepas halaman ini, satu container yang menguasai port 80 dan 443 serta menghalakan trafik ke tempat lain mengikut hostname, dengan TLS. (Datang daripada persediaan Traefik v2 yang lama? Panduan migrasi Traefik v2 ke v3 merangkumi penamaan semula dan perubahan peraturan.)
Sahkan ikatan (bind) selepas memulakan stack: sudo ss -tlnp | grep 8080 sepatutnya menunjukkan 127.0.0.1:8080, bukan 0.0.0.0:8080 atau *:8080.
Volum bernama vs bind mount
db-data:/var/lib/postgresql/data ialah volum bernama: Docker mencipta dan mengurus direktori di bawah /var/lib/docker/volumes/ dan melekapkannya (mount) ke dalam container. Alternatifnya ialah bind mount, ./data:/var/lib/postgresql/data, yang memetakan laluan yang anda pilih pada hos.
Pembahagian yang berkesan dalam praktiknya: volum bernama untuk data yang hanya disentuh oleh container, terutamanya pangkalan data, kerana Docker memulakan volum dengan pemilikan yang dijangkakan oleh imej dan keizinan fail berfungsi secara automatik. Bind mount untuk fail yang anda sentuh daripada hos, fail konfigurasi yang anda sunting dengan editor teks, pustaka media yang anda rsync, apa sahaja yang anda mahu laluannya jelas. Kegagalan bind-mount yang klasik ialah pemilikan: container berjalan sebagai UID 999, direktori hos anda dimiliki oleh UID 1000, dan aplikasi mati semasa permulaan dengan permission denied dalam lognya. Volum bernama menjadikan kelas pepijat itu hampir hilang, dengan kos data berada pada laluan yang diuruskan oleh Docker, yang dibincangkan di bawah.
environment dan .env, jauhkan rahsia daripada git
${POSTGRES_PASSWORD} tidak dibaca daripada shell anda; Compose melakukan interpolasi daripada fail bernama .env yang terletak bersebelahan dengan compose.yml. Ciptakannya:
cat > .env <<'EOF'
POSTGRES_PASSWORD=change-me-to-something-long
ADMIN_PASSWORD=change-me-too
EOF
chmod 600 .env
echo ".env" >> .gitignoreJana nilai sebenar dengan openssl rand -hex 24. Hex, bukan base64, secara sengaja: kata laluan ini akan berada di dalam rentetan sambungan DATABASE_URL, dan aksara /, +, dan = yang dihasilkan oleh base64 akan merosakkan penghuraian URL, kegagalan yang muncul sebagai ralat pengesahan, bukan ralat sintaks, dan membuang masa sepanjang malam. Baris .gitignore diletakkan sebelum commit pertama: fail compose selamat untuk diterbitkan dan diletakkan dalam kawalan versi, fail .env tidak pernah selamat, dan rahsia yang telah menyentuh sejarah git ialah rahsia yang perlu anda tukar (rotate). Jika anda memulakan stack dengan pemboleh ubah yang hilang, Compose memberi amaran dengan jelas dan meneruskan dengan rentetan kosong, yang bagi kata laluan Postgres bermakna deployment yang rosak:
WARN[0000] The "POSTGRES_PASSWORD" variable is not set. Defaulting to a blank string.docker compose config mencetak fail yang telah diinterpolasi sepenuhnya, cara terpantas untuk menyemak apa yang akan diterima oleh container; ingat bahawa keluarannya termasuk rahsia anda.
depends_on tidak menunggu apa-apa, melainkan anda menambah healthcheck
depends_on: [db] kosong hanya mengawal urutan permulaan: Compose melancarkan Postgres dahulu dan aplikasi seketika kemudian, sementara Postgres masih mengambil masa beberapa saat untuk menerima sambungan. Aplikasi mencapai pangkalan data, gagal, dan ranap atau cuba semula bergantung pada betapa baik ia ditulis.
Versi yang boleh dipercayai ialah apa yang digunakan oleh fail di atas: servis db mentakrifkan healthcheck (Postgres menyediakan pg_isready untuk tujuan ini), dan aplikasi mengisytiharkan depends_on dengan condition: service_healthy. Compose memulakan pangkalan data, meninjau (poll) semakan setiap 10 saat, dan hanya memulakan Miniflux sebaik sahaja semakan itu lulus. Jika pangkalan data tidak pernah menjadi sihat (contohnya kata laluan salah, volum rosak), aplikasi tidak akan bermula dan Compose memberitahu anda dependensi mana yang gagal:
dependency failed to start: container miniflux-db-1 is unhealthyMesej itu menunjukkan anda kepada docker compose logs db, tempat ralat sebenar berada.
restart: unless-stopped
restart: unless-stopped pada kedua-dua servis bermakna container akan kembali selepas ranap dan selepas but semula VPS, tetapi kekal mati jika anda sengaja menjalankan docker compose stop. Alternatif always menghidupkan semula container walaupun selepas pemberhentian manual, yang jarang sekali menjadi niat anda. Tanpa polisi restart, but semula kemas kini kernel pada pukul 4 pagi akan mematikan servis anda secara senyap sehingga anda menyedarinya.
Kata kerja harian
Segala tugasan harian melibatkan lima arahan yang dijalankan dari direktori projek.
docker compose up -d # create and start; idempotent, recreates only what changed
docker compose ps # status, ports, and health of this project's containers
docker compose logs -f miniflux # follow one service's logs; --tail 100 for recent history
docker compose pull && docker compose up -d # upgrade to the pinned tags
docker compose down # stop and remove containers and the networkup -d selamat untuk dijalankan berulang kali. Ia membandingkan fail dengan keadaan sebenar dan hanya menyentuh servis yang konfigurasi atau imejnya telah berubah. Pasangan naik taraf mengambil apa sahaja yang ditunjuk oleh tag yang anda tetapkan: keluaran tampalan di bawah postgres:16-alpine, tiada apa-apa untuk tetapan tepat sehingga anda mengubahnya, itulah tujuannya. Imej lama akan terkumpul selepas naik taraf; tuntut semula ruang cakera dengan docker image prune -f.
Sekarang, arahan yang bersifat merosakkan, disebut dengan tegas: docker compose down adalah selamat, kontena dan rangkaian boleh dibuang, dan data anda berada dalam volum. docker compose down -v memadamkan volum yang dinamakan juga. Itu adalah pangkalan data anda, hilang serta-merta, tanpa gesaan pengesahan dan tanpa fungsi buat asal. Flag -v wujud untuk meruntuhkan eksperimen; pada stack yang menyimpan data sebenar, layan ia seperti anda melayan rm -rf. Tiada tong sampah di bawah /var/lib/docker/volumes/.
Untuk shell sekali guna di dalam kontena yang sedang berjalan: docker compose exec db psql -U miniflux membawa anda ke dalam pangkalan data, dan docker compose exec miniflux sh memberikan anda shell dalam aplikasi tersebut.
Lokasi sebenar data anda
Named volumes menerima awalan projek, jadi db-data dalam direktori bernama miniflux menjadi miniflux_db-data:
docker volume ls
docker volume inspect miniflux_db-dataOutput inspect mengandungi baris yang penting:
"Mountpoint": "/var/lib/docker/volumes/miniflux_db-data/_data"Direktori tersebut ialah pangkalan data, dimiliki oleh root, berada pada sistem fail hos, dan ia kekal selepas down, naik taraf, dan pembinaan semula container. Ia juga merupakan perkara utama yang mesti diambil oleh sandaran (backup) anda.
Sandarkan volume bernama
Corak standardnya ialah menggunakan kontena sementara yang melekapkan volume dalam mod baca sahaja bersebelahan dengan direktori hos, kemudian melakukan proses tar:
docker run --rm \
-v miniflux_db-data:/data:ro \
-v "$PWD":/backup \
alpine:3.22 tar czf /backup/miniflux-db-$(date +%F).tar.gz -C /data .Tiada pemasangan diperlukan, tiada proses yang kekal berjalan, dan pemulihan adalah imej cermin, dengan tar xzf ke dalam volume kosong yang baharu menggunakan pelekapan yang diterbalikkan.
Satu peringatan untuk pangkalan data: melakukan tar pada direktori data Postgres yang sedang berjalan boleh menangkap keadaan pertengahan penulisan yang tidak akan bermula dengan sempurna. Sama ada docker compose stop untuk beberapa saat proses tar berlangsung, atau lebih baik, lakukan logical dump, yang konsisten secara binaan:
docker compose exec -T db pg_dump -U miniflux miniflux | gzip > miniflux-$(date +%F).sql.gzFlag -T melumpuhkan pseudo-terminal yang diperuntukkan oleh Compose secara lalai, kerana menyalurkan output dump melalui TTY boleh merosakkannya. Masukkan salah satu daripada ini ke dalam cron dan salin hasilnya keluar dari VPS; sandaran yang berada pada cakera yang sama dengan data yang dilindunginya hanyalah satu salinan, bukan sandaran. Panduan Nextcloud membina rutin berjadual penuh berdasarkan tepat dua corak ini.
Mod kegagalan, berserta rentetan yang akan anda lihat
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock, anda belum berada dalam kumpulan docker, atau anda sudah berada di dalamnya tetapi sesi semasa bermula sebelum perubahan tersebut. id menunjukkan kumpulan efektif anda; newgrp docker membetulkan shell semasa, manakala log keluar dan masuk semula akan membetulkan kesemuanya.
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?, masalah berbeza: daemon itu sendiri tidak berjalan. sudo systemctl status docker dan sudo journalctl -u docker -n 50 menyatakan puncanya. Pada VPS, punca klasik ialah cakera penuh, df -h /var/lib/docker dahulu.
Bind for 127.0.0.1:8080 failed: port is already allocated, bekas lain sudah menerbitkan port hos tersebut. docker ps menunjukkan bekas yang mana; bekas lama daripada docker run eksperimen beberapa minggu lalu biasanya menjadi punca. Jika docker ps bersih, proses bukan Docker yang memegang port tersebut: sudo ss -tlnp | grep 8080 menamakan proses itu.
yaml: line 14: did not find expected key, ralat inden pada atau tepat di atas baris yang dinamakan. Fail Compose menggunakan format YAML: inden dua ruang, hanya ruang kosong, dan aksara tab di mana-mana sahaja akan menyebabkan kegagalan. docker compose config mengesahkan fail tersebut tanpa memulakan apa-apa, dan menjalankannya selepas setiap suntingan adalah tabiat yang baik.
Kejutan ufw tidak mencetak sebarang ralat, itulah yang menjadikannya berbahaya: deployment berjaya, ufw status kelihatan betul, dan imbasan port dari luar tetap menemui pangkalan data anda. Baca semula bahagian port di atas, semak setiap entri ports: untuk awalan 127.0.0.1: yang hilang, dan sahkan daripada mesin yang berbeza dengan curl http://your-vps-ip:8080, connection refused ialah jawapan yang anda mahukan.
Dari sini, panduan Traefik menukarkan tindanan tunggal ini kepada banyak aplikasi di sebalik satu titik masuk HTTPS, dan apa yang berbaloi untuk di-self-host pada tahun 2026 ialah senarai beli-belah untuk dijalankan melaluinya. Apabila beberapa tindanan tersebut berjalan dan setiap satunya mempunyai borang log masuk sendiri, pelayan SSO self-hosted seperti Authentik akan menggabungkannya semula ke dalam satu akaun di sebalik proksi yang sama.
Pelayan permainan seperti pelayan Minecraft pada VPS ialah projek Compose pertama yang sesuai untuk latihan. Jika anda lebih suka belajar menggunakan sesuatu yang dibuka setiap hari, openGym, penjejak senaman yang dihos sendiri ialah tindanan kecil yang dipakukan pada tag git, bukan tag imej. Tindanan ini memerlukan TLS di hadapan sebelum anda mendaftarkan passkey pertama. Foto biasanya perkara pertama yang mahu dipindahkan kembali daripada cloud pihak lain. perbandingan PhotoPrism dan Immich membantu menentukan keperluan RAM minimum serta rutin sandaran yang perlu anda gunakan sebelum mengikat volume pada salah satu daripadanya. Apabila dua servis tidak lagi mencukupi, menyediakan AFFiNE sebagai ruang kerja gaya Notion menggunakan corak yang sama dengan empat container. Ini juga ujian yang baik untuk menentukan sama ada tag yang dipakukan, healthcheck dan volume bernama di atas sudah menjadi amalan biasa.
FAQ
Mengapa saya mendapat ralat "permission denied while trying to connect to the Docker daemon socket"?
Pengguna anda tidak berada dalam kumpulan docker, atau telah ditambah selepas sesi semasa bermula; keahlian kumpulan hanya berkuat kuasa semasa log masuk. Jalankan sudo usermod -aG docker $USER, kemudian newgrp docker atau log keluar dan masuk semula, dan sahkan dengan id. Kumpulan ini memberikan akses setara root kepada hos, jadi hanya tambah pengguna yang anda percayai untuk diberikan akses sudo.
Adakah docker compose down memadamkan data saya?
Perintah docker compose down biasa tidak memadamkan data; ia hanya membuang kontena dan rangkaian projek. Volume bernama akan kekal dan up -d seterusnya akan menyambungkannya semula. docker compose down -v ialah bentuk yang memusnahkan data: ia memadamkan volume bernama, termasuk pangkalan data anda, tanpa pengesahan dan tidak boleh dibatalkan. Jangan sekali-kali jalankan -v pada stack yang mengandungi data sebenar melainkan anda mempunyai sandaran yang telah disahkan.
Apakah perbezaan antara docker-compose dan docker compose?
docker-compose (dengan tanda sempang) ialah Compose v1, binari Python kendiri yang telah tamat tempoh hayat pada tahun 2023 dan tidak sepatutnya dipasang pada pelayan baharu. docker compose (dengan ruang) ialah Compose v2, pemalam Go untuk Docker CLI yang dipasang sebagai docker-compose-plugin daripada repositori apt Docker. Perintah dan YAML hampir serasi sepenuhnya, jadi apabila tutorial lama menyebut docker-compose up, taipkan docker compose up.
Mengapa saya boleh mencapai kontena Docker saya dari internet walaupun ufw menyekat port tersebut?
Kerana Docker menerbitkan port dengan peraturan DNAT dalam chain PREROUTING pada iptables, dan paket yang ditulis semula melalui laluan FORWARD menerusi chain milik Docker sendiri, ia tidak pernah sampai ke chain INPUT di mana peraturan ufw digunakan. Oleh itu, ufw deny 8080 tidak memberi kesan kepada port kontena yang diterbitkan. Selesaikan masalah ini pada puncanya: terbitkan ke 127.0.0.1: dan dedahkan servis melalui reverse proxy.
Patutkah saya menggunakan named volume atau bind mount?
Gunakan named volume untuk data yang hanya disentuh oleh kontena, terutamanya pangkalan data, kerana Docker menetapkan pemilikan yang dijangkakan oleh imej dan keizinan akan berfungsi secara automatik. Gunakan bind mount untuk fail yang anda uruskan juga dari hos: konfigurasi yang anda sunting, media yang anda muat naik, atau apa-apa sahaja yang anda mahu lokasinya jelas. Jika kontena gagal bermula dengan permission denied pada bind mount, ketidakpadanan UID antara hos dan kontena adalah perkara pertama yang perlu diperiksa.