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

Perbezaan Menjalankan Docker pada VPS Berbanding PC

Menjalankan Docker pada VPS berbeza kerana RAM terhad, port terdedah di luar UFW, kontena tidak auto-restart, dan storan cepat penuh. Ketahui cara mengelakkan isu ini.

Perubahan apabila menjalankan Docker pada VPS

Docker pada VPS menjalankan enjin dan imej yang sama seperti Docker pada komputer riba anda, jadi setiap arahan yang anda sudah tahu masih berfungsi. Perbezaannya ialah persekitaran di sekelilingnya. Komputer riba mempunyai memori yang mencukupi, firewall yang tidak diimbas oleh sesiapa, dan cakera yang cukup besar sehingga anda tidak perlu memantaunya. Pelayan sewaan mempunyai had memori yang tetap, alamat IP awam yang akan diimbas dalam masa beberapa minit selepas dihidupkan, dan sistem fail root yang akan dipenuhi oleh Docker tanpa bertanya.

Empat perbezaan ini menyebabkan kebanyakan masalah pada pelayan kecil:

  • Memori adalah terhad, dan kernel akan menyelesaikan kekurangan memori dengan mematikan proses.
  • Port yang diterbitkan akan terus menembusi UFW (uncomplicated firewall), kerana Docker menulis peraturan firewallnya sendiri.
  • Kontena tidak akan bermula semula selepas but semula (reboot) melainkan anda telah menetapkannya lebih awal.
  • Imej, kontena, volum dan cache binaan akan terus berkembang sehingga cakera penuh.

Setiap bahagian di bawah menamakan kegagalan tersebut, rentetan (string) yang akan anda lihat, dan panduan yang membetulkannya secara terperinci. Jika anda belum menulis fail compose, baca Asas Docker Compose pada VPS terlebih dahulu dan kembali ke sini. Halaman ini mengandaikan anda sudah boleh menjalankan stack.

Berapakah jumlah RAM yang digunakan oleh kontena Docker?

Jumlahnya lebih kecil daripada jangkaan kebanyakan orang. Kontena ialah proses di dalam cgroup (control group), bukannya mesin maya, jadi tiada kernel tetamu dan tiada peruntukan tetap. Kosnya adalah berdasarkan apa sahaja yang disentuh oleh proses di dalamnya. Itulah sebabnya satu tindanan (stack) penuh boleh dimuatkan dalam 2 GB, sedangkan tindanan yang sama jika dibina menggunakan mesin maya tidak akan muat.

Angka di bawah adalah nombor melahu (idle) tipikal untuk imej stok pada Ubuntu 24.04 dengan konfigurasi lalai, dibaca daripada docker stats beberapa minit selepas dimulakan. Ia merupakan titik permulaan untuk perancangan, bukan penanda aras bagi beban kerja anda. Jalankan docker stats --no-stream pada pelayan anda sendiri sebelum anda mempercayai mana-mana angka, termasuk angka-angka ini.

ChartTypical idle container memory, stock images, megabytes
The data behind this chart
[
  {
    "label": "nginx",
    "idle_mb": 8,
    "budget_mb": 64
  },
  {
    "label": "Redis 7",
    "idle_mb": 12,
    "budget_mb": 128
  },
  {
    "label": "Traefik v3",
    "idle_mb": 40,
    "budget_mb": 128
  },
  {
    "label": "PostgreSQL 16",
    "idle_mb": 45,
    "budget_mb": 512
  },
  {
    "label": "Uptime Kuma",
    "idle_mb": 95,
    "budget_mb": 256
  },
  {
    "label": "MariaDB 11",
    "idle_mb": 190,
    "budget_mb": 512
  },
  {
    "label": "Nextcloud (Apache)",
    "idle_mb": 210,
    "budget_mb": 768
  }
]

Dua lajur tersebut mempunyai fungsi yang berbeza. idle_mb ialah jumlah yang digunakan oleh kontena semasa tidak melakukan apa-apa. budget_mb ialah jumlah yang perlu dikhaskan semasa anda merancang, kerana penggunaan sebenar tidak berada dalam keadaan melahu. PostgreSQL melahu sekitar 45 MB dan memerlukan 512 MB sebaik sahaja sambungan, pengisihan (sorts) dan cache aktif. Rancang menggunakan lajur bajet. Lakukan penyahpepijatan menggunakan lajur melahu.

Perhatikan bentuk bagi 7 baris tersebut. nginx melahu pada 8 MB dan Nextcloud pada 210 MB. Proksi di hadapan aplikasi anda hampir tidak menggunakan sumber. Pangkalan data dan aplikasi PHP adalah perkara yang menentukan saiz pelayan anda.

Satu amaran mengenai docker stats: angka memori tersebut merangkumi cache halaman yang ditarik masuk oleh bacaan fail kontena itu sendiri, jadi ia akan meningkat untuk seketika selepas dimulakan dan kemudian menjadi stabil. Pantau ia selama sejam sebelum anda membuat keputusan bahawa sesuatu sedang mengalami kebocoran memori.

Menentukan saiz VPS: apa yang muat dalam 2 GB, 4 GB dan 8 GB

Tolak dahulu bahagian yang digunakan oleh hos. Kernel, systemd, journald, sshd dan daemon Docker semuanya menggunakan RAM yang sama dengan kontena anda, dan dockerd dengan containerd mengambil sekitar 100 MB daripadanya. Anda juga memerlukan memori bebas untuk page cache, serta untuk lonjakan penggunaan semasa pembinaan imej atau proses dump pangkalan data dijalankan.

ChartRAM budget by plan size, megabytes
The data behind this chart
[
  {
    "plan": "2 GB VPS",
    "total_mb": 2048,
    "host_reserve_mb": 768,
    "container_mb": 1280
  },
  {
    "plan": "4 GB VPS",
    "total_mb": 4096,
    "host_reserve_mb": 1024,
    "container_mb": 3072
  },
  {
    "plan": "8 GB VPS",
    "total_mb": 8192,
    "host_reserve_mb": 1536,
    "container_mb": 6656
  }
]

host_reserve_mb merangkumi sistem pengendalian, daemon Docker dan ruang tambahan yang memastikan pelayan kekal responsif di bawah beban. Apa yang tinggal ialah container_mb, dan itulah satu-satunya jumlah yang boleh anda gunakan. Rizab ini meningkat mengikut pelan, daripada 768 MB pada pelayan terkecil kepada 1536 MB pada pelayan terbesar, kerana pelayan yang lebih besar menjalankan lebih banyak kontena, menulis lebih banyak log dan memerlukan lebih banyak page cache.

Pelan 2 GB meninggalkan 1280 MB untuk kontena. Gunakan 512 MB daripadanya untuk PostgreSQL dan 128 MB untuk Traefik, dan separuh daripadanya sudah habis digunakan. Selebihnya cukup untuk dua aplikasi kecil dengan anggaran 256 MB setiap satu. Ini adalah pelayan yang sebenar dan berguna. Ia tidak mempunyai ruang untuk Nextcloud dan kluster carian di atasnya.

Pelan 4 GB meninggalkan 3072 MB, iaitu ruang di mana pangkalan data, reverse proxy, tiga aplikasi dan satu kontena pemantauan boleh dimuatkan serentak. Ini adalah saiz terkecil yang berbaloi digunakan untuk apa sahaja yang penting bagi anda, kerana memori tambahan itulah yang akan menampung kesan jika berlaku deploy yang bermasalah.

Pelan 8 GB meninggalkan 6656 MB daripada jumlah 8192 MB, dan had biasanya beralih daripada memori kepada CPU atau throughput cakera. Jika pengiraan menunjukkan stack anda tidak muat, beli pelan yang lebih besar daripada cuba melakukan penalaan: kos sebenar VPS menjelaskan nilai gigabait tambahan tersebut setiap bulan.

Dua peraturan memastikan pengiraan kekal tepat. Letakkan had memori pada setiap servis, supaya satu proses yang tidak terkawal tidak menjejaskan keseluruhan pelayan. Dan jangan gunakan semua bajet memori, kerana docker compose build dan pg_dump kedua-duanya memerlukan memori pada saat yang paling kritikal. Had memori dalam Docker Compose mengandungi sintaks dan perangkap yang perlu dielakkan.

Mengapa kontena saya keluar dengan kod 137?

Ini kerana kernel telah menamatkan proses tersebut. 137 adalah hasil daripada 128 ditambah 9, dan isyarat 9 ialah SIGKILL. Kontena tersebut meminta memori melebihi had yang dibenarkan, lalu OOM (out of memory) killer menamatkannya.

CONTAINER ID   IMAGE         STATUS
9f2c1a4d7b3e   postgres:16   Exited (137) 4 minutes ago

Sahkan punca tersebut dan jangan hanya meneka:

docker inspect my-db | grep -i oomkilled
sudo journalctl -k | grep -i "out of memory"

"OOMKilled": true bermaksud kontena telah mencapai had cgroupnya sendiri, dan log kernel akan menamakan proses yang dipilih untuk ditamatkan:

Memory cgroup out of memory: Killed process 2417 (postgres) total-vm:1284416kB

Ini adalah senario yang lebih baik, kerana kerosakan hanya terhad kepada satu kontena. Senario buruk berlaku apabila kontena tidak mempunyai sebarang had. Tanpa had, siling memorinya adalah keseluruhan mesin; kebocoran pada satu servis akan melumpuhkan hos, dan kernel akan memilih mangsa berdasarkan saiz di seluruh sistem. Baris log akan kehilangan awalan Memory cgroup dan memaparkan Out of memory: Killed process 2417 (postgres). Proses yang dipilih selalunya adalah pangkalan data anda, manakala kontena yang mengalami kebocoran memori terus berjalan. Itulah sebabnya menetapkan had pada setiap servis lebih penting daripada nilai tepat bagi mana-mana had tunggal.

Swap mengubah masa tindak balas, bukan pengiraan memori. Kebanyakan imej VPS diedarkan tanpa swap. Semak dengan swapon --show, yang tidak akan memaparkan apa-apa jika swap tiada. Fail swap memberikan ruang kepada kernel untuk menyimpan halaman memori yang tidak aktif, yang memberi anda masa beberapa minit untuk menyedari masalah yang berlaku.

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
free -h

free -h kini sepatutnya menunjukkan jumlah bukan sifar pada baris Swap. Swap tidak menambah RAM. Pelayan yang berada di bawah tekanan memori berterusan akan menjadi terlalu perlahan sehingga anda tidak dapat melakukan SSH untuk membaikinya, jadi anggap swap sebagai penampan amaran dan betulkan saiz memori anda.

Mengapa UFW tidak menyekat port Docker saya yang diterbitkan?

Kerana trafik tersebut tidak pernah sampai ke rantaian (chain) yang dikawal oleh UFW. Apabila anda menerbitkan port dengan -p 5432:5432 atau entri ports: dalam compose, daemon tersebut menulis peraturan DNAT (destination network address translation) ke dalam jadual nat dan peraturan accept ke dalam rantaian DOCKER miliknya sendiri. Paket yang ditujukan kepada kontena akan diteruskan (forwarded) ke kontena tersebut dan bukannya dihantar kepada hos, jadi ia dikendalikan dalam laluan FORWARD dan tidak pernah melalui peraturan INPUT yang ditulis oleh UFW.

Anda boleh memerhati perkara ini berlaku pada pelayan:

sudo ufw status | grep 5432
sudo iptables -t nat -L DOCKER -n | grep 5432

UFW mungkin memaparkan 5432 DENY IN Anywhere sementara jadual nat menyimpan peraturan DNAT tcp ... to:172.18.0.2:5432 untuk port yang sama. Dari mesin lain, nc -vz your.server.ip 5432 masih boleh bersambung. Pangkalan data berada di internet awam manakala tembok api menyatakan ia tidak boleh diakses.

Penyelesaiannya adalah dengan mengurangkan penerbitan port. Kontena dalam satu projek compose berkongsi rangkaian yang sama dan boleh berhubung antara satu sama lain menggunakan nama servis, jadi pangkalan data yang hanya melayani aplikasi di sebelahnya tidak memerlukan entri ports: langsung. Apabila anda mahukan akses tempatan, ikat (bind) penerbitan tersebut kepada loopback:

services:
  db:
    image: postgres:16
    ports:
      - "127.0.0.1:5432:5432"

Selepas docker compose up -d, nc -vz your.server.ip 5432 dari luar akan gagal, dan psql -h 127.0.0.1 -p 5432 pada mesin tersebut masih berfungsi. Dalam tindanan (stack) kecil yang sihat, hanya reverse proxy yang menerbitkan apa-apa, iaitu pada port 80 dan 443. Mengapa port yang diterbitkan Docker memintas UFW membincangkan rantaian DOCKER-USER bagi kes di mana anda perlu menerbitkan port dan masih mahu menapisnya, manakala Asas tembok api UFW membincangkan peraturan hos di peringkat bawah.

Mengapa kontena saya hilang selepas but semula?

Kerana tiada arahan yang menyuruhnya kembali berjalan. Kontena dicipta dengan polisi mula semula no melainkan anda menetapkannya, jadi but semula akan membiarkannya dalam keadaan berhenti dan daemon tidak akan mengambil tindakan. But semula bukanlah perkara luar biasa pada VPS: kemas kini kernel daripada naik taraf automatik, penyelenggaraan penyedia, dan urutan OOM di atas semuanya berakhir dengan but semula.

Dua perkara perlu dipenuhi. Daemon mesti bermula semasa but:

systemctl is-enabled docker

Arahan tersebut memaparkan enabled pada pemasangan Ubuntu standard. Kemudian, setiap servis memerlukan polisi:

services:
  app:
    image: ghcr.io/example/app:1.4
    restart: unless-stopped

unless-stopped akan menghidupkan semula kontena selepas but semula dan menghormati kontena yang anda hentikan secara sengaja. always juga akan menghidupkan semula kontena yang anda hentikan dengan sengaja setiap kali daemon bermula semula, yang mungkin mengejutkan semasa proses penyahpepijatan. Menyunting fail sahaja tidak mencukupi, kerana polisi mula semula ditetapkan semasa kontena dicipta. Jalankan docker compose up -d supaya ia dicipta semula, kemudian semak nilai semasa:

docker inspect my-app | grep -A3 RestartPolicy

Kemudian, but semula pelayan secara sengaja dan jalankan docker compose ps dalam direktori projek. Stak yang bertahan selepas but semula yang dirancang akan bertahan selepas but semula yang tidak dirancang. Jika stak anda memerlukan jaminan urutan atau tugasan sekali jalan semasa but, unit systemd adalah alat yang lebih baik: memulakan Docker Compose semasa but mengandungi fail unit tersebut. Untuk mengetahui sama ada kontena yang kembali berjalan benar-benar berfungsi, tambahkan Compose healthchecks.

Mengapa cakera VPS saya penuh?

Ini kerana Docker menyimpan segala-galanya sehingga anda mengarahkannya untuk berhenti. Setiap tag imej yang pernah anda tarik, setiap container yang dihentikan, setiap volume tanpa nama yang ditinggalkan oleh proses penciptaan semula, dan setiap lapisan cache binaan kekal di dalam cakera. Pada sistem fail root bersaiz 40 GB atau 80 GB, yang merupakan saiz biasa bagi pelan ini, ia akan menyebabkan gangguan perkhidmatan dalam tempoh beberapa bulan, bukan tahun.

Cakera penuh tidak kelihatan seperti kerosakan sistem (crash). Anda akan menerima no space left on device daripada container, daripada apt, daripada journald dan daripada docker pull dalam jam yang sama. PostgreSQL akan berhenti menerima penulisan data. Pelayan masih hidup, yang menjadikannya lebih sukar dikesan berbanding gelung but semula (reboot loop).

Periksa sebelum anda memadam:

docker system df
df -h /

docker system df membahagikan jumlah penggunaan kepada imej, container, volume tempatan dan cache binaan, dengan lajur RECLAIMABLE di sebelah setiap satu. Pada pelayan yang membina imejnya sendiri, cache binaan biasanya merupakan baris yang paling besar.

docker image prune -a
docker builder prune
docker system df

docker image prune -a membuang setiap imej yang tidak digunakan oleh mana-mana container. docker builder prune membersihkan cache binaan. Kedua-duanya selamat dilakukan semasa servis sedang berjalan, kerana apa-apa yang sedang digunakan akan dilangkau. Perkara yang tidak selamat ialah docker system prune --volumes, yang memadamkan setiap volume yang tidak dirujuk oleh mana-mana container pada masa ini. Stack yang anda hentikan untuk hujung minggu mempunyai bentuk yang tepat seperti itu, dan volume pangkalan datanya akan turut terpadam. Baca bind mounts versus named volumes sebelum anda menaip flag tersebut, dan buat sandaran (backup) terlebih dahulu.

Log container adalah punca pertumbuhan yang lebih senyap. Driver json-file lalai tidak mempunyai had saiz, jadi satu container yang banyak menulis log akan menghasilkan gigabait data ke dalam /var/lib/docker/containers. Hadkan saiznya untuk setiap container di dalam /etc/docker/daemon.json:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

Gunakan tetapan ini dengan sudo systemctl restart docker, yang akan memulakan semula container anda, jadi pilih waktu yang sesuai. Had tersebut terpakai kepada container yang dicipta selepas perubahan dibuat, jadi cipta semula container yang sedang berjalan dengan docker compose up -d --force-recreate dan sahkan:

docker inspect my-app | grep -A5 LogConfig
sudo du -sh /var/lib/docker/containers

Output inspect sepatutnya menunjukkan max-size telah ditetapkan. Jika ia kosong, container tersebut dicipta sebelum perubahan dibuat dan masih menulis log tanpa had.

Tabiat yang mengekalkan kesihatan pelayan Docker kecil

Tiada satu pun daripada ini memerlukan papan pemuka atau alatan yang perlu anda pelajari.

  • Jalankan docker system df dan df -h / pada hari pertama setiap bulan. Dua arahan, tiga puluh saat, dan anda akan melihat trend tersebut jauh sebelum ia menjadi gangguan perkhidmatan.
  • Berikan setiap servis had memori, termasuk servis yang anda pasti bersaiz kecil. Had ini menukarkan gangguan seluruh hos kepada hanya satu kontena yang dimulakan semula.
  • Pantau pelayan dari lokasi lain, supaya anda mendapat makluman tentang tekanan memori atau cakera sebelum kernel bertindak. Uptime Kuma berjalan dalam kontena dan melahu pada sekitar 95 MB.
  • Sandarkan volum, bukan kontena. Kontena boleh dibuang tetapi volum tidak. sandaran restic pada VPS merangkumi jadual dan ujian pemulihan.
  • Sematkan tag imej dalam fail compose dan kemas kinikannya pada hari yang anda pilih. Dengan latest, versi yang anda peroleh daripada docker compose pull seterusnya adalah apa sahaja yang dikeluarkan pada pagi itu.

VPS kecil yang menjalankan Docker kekal sihat selama bertahun-tahun apabila empat nombor kekal dalam julat: bajet memori, senarai port yang diterbitkan, polisi mulakan semula pada setiap servis, dan ruang cakera kosong. Segala-galanya adalah Docker yang sama yang anda sudah jalankan di rumah.

FAQ

Berapakah RAM yang diperlukan untuk menjalankan Docker pada VPS?

Docker sendiri menggunakan sumber yang kecil. Daemon dan containerd secara bersama menggunakan sekitar 100 MB, manakala keperluan selebihnya bergantung pada kontena anda. Peruntukkan bahagian pelayan terlebih dahulu: 768 MB pada mesin 2048 MB untuk sistem pengendalian, daemon dan ruang simpanan, yang meninggalkan 1280 MB untuk kegunaan anda. Pangkalan data pada 512 MB, reverse proxy pada 128 MB dan dua aplikasi kecil boleh dimuatkan dalam ruang tersebut. Ukur timbunan (stack) anda sendiri dengan docker stats --no-stream dan jangan hanya bergantung pada angka yang diterbitkan.

Bolehkah saya menjalankan Docker pada VPS 1 GB?

Boleh, untuk satu atau dua kontena ringan, dan tambahkan fail swap sebelum anda bermula. Hampir separuh daripada kapasiti mesin 1 GB akan digunakan sebaik sahaja sistem pengendalian dan daemon Docker berjalan, yang meninggalkan ruang untuk satu aplikasi kecil dan satu reverse proxy, tetapi tidak untuk pangkalan data di bawah beban sebenar. Membina imej pada mesin bersaiz tersebut akan gagal atau menyebabkan proses lain ditamatkan, jadi bina imej di tempat lain dan tarik (pull) imej yang telah siap.

Adakah UFW melindungi kontena Docker?

Tidak untuk port yang anda terbitkan (publish). Docker menulis peraturan DNAT dan forward miliknya sendiri, jadi paket yang ditujukan ke port kontena yang diterbitkan akan dihantar terus ke kontena tersebut dan bukannya dihantar ke hos, dan peraturan INPUT yang diuruskan oleh UFW tidak akan melihatnya. ufw deny 5432 boleh kekal aktif sementara port tersebut menjawab permintaan daripada internet. Terbitkan ke loopback dengan 127.0.0.1:5432:5432, biarkan servis dalaman tidak diterbitkan, atau tapis dalam rantaian DOCKER-USER.

Adakah kontena saya akan bermula semula selepas VPS but semula (reboot)?

Hanya jika ia dicipta dengan polisi mulakan semula (restart policy). Tetapkan restart: unless-stopped pada setiap servis, jalankan docker compose up -d supaya kontena dicipta semula dengan polisi tersebut, dan sahkan systemctl is-enabled docker memaparkan enabled. Kemudian lakukan but semula secara sengaja dan periksa docker compose ps. Polisi mulakan semula yang tidak pernah anda uji bukanlah polisi yang boleh dipercayai.

Berapa kerap saya perlu membersihkan (prune) imej Docker?

Sebulan sekali sudah memadai untuk kebanyakan pelayan kecil, atau bila-bila masa docker system df melaporkan ruang yang boleh dituntut semula yang anda perlukan. docker image prune -a dan docker builder prune kedua-duanya selamat digunakan semasa servis sedang berjalan, kerana imej dan cache yang sedang digunakan akan dilangkau. Elakkan docker system prune --volumes melainkan anda tahu dengan tepat volum mana yang tidak dirujuk, kerana ia akan memadamkan data mana-mana timbunan (stack) yang kebetulan sedang berhenti.