SSD Nodes Learn 🎉 VPS mulai $5.50/bln
Panduan Matt ConnorOleh Matt Connor · Diperbarui 2026-08-13

Docker di VPS: Apa yang Sebenarnya Berubah?

Docker di VPS memakai engine yang sama, tetapi RAM terbatas, port yang dipublikasikan dapat melewati UFW, container tidak otomatis aktif setelah reboot, dan disk bisa penuh.

Perubahan saat menjalankan Docker pada VPS

Docker pada VPS menggunakan engine dan image yang sama seperti Docker pada laptop Anda, sehingga setiap perintah yang sudah Anda kenal tetap berfungsi. Perbedaannya terletak pada ruang sumber daya yang tersedia. Laptop memiliki memori cadangan, firewall yang tidak dipindai siapa pun, dan disk yang cukup besar sehingga Anda tidak perlu memantaunya. Server sewaan memiliki batas memori tetap, alamat IP publik yang mulai dipindai dalam beberapa menit setelah boot, dan root filesystem yang akan dipenuhi Docker tanpa meminta izin.

Empat perbedaan berikut menyebabkan sebagian besar masalah pada server kecil:

  • Memori terbatas, dan kernel mengatasi kekurangan memori dengan menghentikan proses.
  • Port yang dipublikasikan langsung melewati UFW (uncomplicated firewall), karena Docker menulis aturan firewall-nya sendiri.
  • Container tidak otomatis berjalan kembali setelah reboot, kecuali Anda telah mengaturnya sebelumnya.
  • Image, container, volume, dan cache build terus bertambah hingga disk penuh.

Setiap bagian di bawah ini menjelaskan kegagalan, string yang benar-benar akan Anda lihat, dan panduan yang membahas solusinya secara mendalam. Jika Anda belum menulis file compose, baca Dasar-Dasar Docker Compose pada VPS terlebih dahulu, lalu kembali ke halaman ini. Halaman ini mengasumsikan Anda sudah dapat menjalankan sebuah stack.

Berapa banyak RAM yang digunakan container Docker?

Lebih sedikit daripada perkiraan kebanyakan orang. Container adalah proses dalam cgroup (control group), bukan virtual machine. Karena itu, container tidak memiliki kernel guest dan tidak memiliki alokasi tetap. Penggunaan memorinya bergantung pada bagian yang diakses oleh proses di dalamnya. Karena itu, seluruh stack dapat berjalan dalam 2 GB, sedangkan stack yang sama jika dibangun dari virtual machine tidak akan muat.

Angka di bawah ini adalah angka idle yang umum untuk image bawaan pada Ubuntu 24.04 dengan konfigurasi default. Angka tersebut dibaca dari docker stats beberapa menit setelah proses start. Gunakan angka ini sebagai dasar perencanaan, bukan sebagai benchmark untuk workload Anda. Jalankan docker stats --no-stream pada server Anda sendiri sebelum mempercayai angka apa pun, termasuk angka di sini.

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
  }
]

Kedua kolom tersebut memiliki fungsi yang berbeda. idle_mb adalah penggunaan container saat tidak melakukan apa pun. budget_mb adalah jumlah yang perlu dicadangkan saat membuat perencanaan, karena penggunaan nyata tidak berada dalam kondisi idle. PostgreSQL menggunakan sekitar 45 MB saat idle dan memerlukan 512 MB setelah koneksi, proses sort, dan cache aktif. Gunakan kolom anggaran untuk perencanaan. Gunakan kolom idle untuk debugging.

Perhatikan pola pada 7 baris tersebut. nginx menggunakan 8 MB saat idle, sedangkan Nextcloud menggunakan 210 MB. Proxy di depan aplikasi Anda hampir tidak menggunakan memori. Database dan aplikasi PHP adalah komponen yang menentukan ukuran server yang diperlukan.

Perhatikan satu hal tentang docker stats: angka memori tersebut mencakup page cache yang dimuat oleh pembacaan file dari container itu sendiri. Karena itu, angkanya meningkat selama beberapa saat setelah start, lalu stabil. Pantau selama satu jam sebelum menyimpulkan bahwa terjadi kebocoran memori.

Ukuran VPS: apa yang muat pada 2 GB, 4 GB, dan 8 GB

Kurangi terlebih dahulu porsi yang digunakan host. Kernel, systemd, journald, sshd, dan Docker daemon menggunakan RAM yang sama dengan container Anda, dan dockerd dengan containerd menggunakan sekitar 100 MB. Anda juga memerlukan memori bebas untuk page cache dan lonjakan penggunaan saat image sedang dibangun atau dump database 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 mencakup sistem operasi, Docker daemon, dan cadangan memori yang membuat server tetap responsif saat beban tinggi. Sisa memori adalah container_mb, dan hanya jumlah inilah yang dapat Anda gunakan. Cadangan tersebut bertambah sesuai paket, dari 768 MB pada server terkecil hingga 1536 MB pada server terbesar, karena server yang lebih besar menjalankan lebih banyak container, menulis lebih banyak log, dan membutuhkan page cache yang lebih besar.

Paket 2 GB menyisakan 1280 MB untuk container. Gunakan 512 MB untuk PostgreSQL dan 128 MB untuk Traefik, maka separuh anggaran tersebut sudah terpakai. Sisanya cukup untuk dua aplikasi kecil dengan penggunaan sekitar 256 MB masing-masing. Ini adalah server yang nyata dan berguna. Namun, kapasitasnya tidak cukup untuk menjalankan Nextcloud dan search cluster sekaligus.

Paket 4 GB menyisakan 3072 MB. Kapasitas ini cukup untuk menjalankan database, reverse proxy, tiga aplikasi, dan satu container pemantauan sekaligus. Ini adalah ukuran terkecil yang layak digunakan untuk layanan penting, karena memori cadangan menyerap dampak dari deployment yang bermasalah.

Paket 8 GB menyisakan 6656 MB dari total 8192 MB. Pada ukuran ini, batas biasanya bergeser dari memori ke CPU atau throughput disk. Jika perhitungan menunjukkan bahwa stack Anda tidak muat, pilih paket yang lebih besar daripada mencoba menyesuaikannya dengan konfigurasi: biaya VPS sebenarnya menjelaskan nilai tambahan gigabyte tersebut per bulan.

Dua aturan membantu menjaga perhitungan tetap akurat. Tetapkan memory limit pada setiap service agar satu proses yang tidak terkendali tidak menghabiskan seluruh kapasitas server. Sisakan bagian atas anggaran, karena docker compose build dan pg_dump sama-sama membutuhkan memori pada saat yang paling tidak menguntungkan. Memory limit di Docker Compose menjelaskan sintaks dan jebakannya.

Mengapa container saya keluar dengan kode 137?

Karena kernel menghentikannya. 137 adalah 128 ditambah 9, dan sinyal 9 adalah SIGKILL. Container meminta memori melebihi batas yang diizinkan, lalu OOM killer menghentikannya.

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

Pastikan penyebabnya, jangan hanya menebak:

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

"OOMKilled": true berarti container mencapai batas cgroup-nya sendiri, dan log kernel menyebutkan proses yang dipilihnya:

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

Ini adalah kondisi yang baik karena dampaknya berhenti pada satu container. Kondisi yang buruk terjadi jika container sama sekali tidak memiliki batas. Tanpa batas, kapasitas maksimumnya adalah seluruh mesin. Kebocoran memori pada satu service dapat menghabiskan sumber daya host, lalu kernel memilih korban berdasarkan ukuran proses di seluruh sistem. Baris log tersebut tidak memiliki awalan Memory cgroup dan berbunyi Out of memory: Killed process 2417 (postgres). Proses yang dipilih sering kali adalah database Anda, sedangkan container yang mengalami kebocoran tetap berjalan. Karena itu, menetapkan batas pada setiap service lebih penting daripada menentukan nilai yang tepat untuk satu batas tertentu.

Swap mengubah waktu terjadinya masalah, bukan perhitungannya. Sebagian besar image VPS dikirim tanpa swap. Periksa dengan swapon --show. Perintah ini tidak menampilkan apa pun jika swap tidak tersedia. File swap memberi kernel tempat untuk menyimpan page yang tidak aktif, sehingga Anda memiliki waktu beberapa menit untuk menyadari adanya masalah.

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 sekarang seharusnya menampilkan total non-zero pada baris Swap. Swap tidak menambah RAM. Server yang terus-menerus mengalami tekanan memori dapat menjadi sangat lambat sehingga Anda tidak dapat masuk melalui SSH untuk memperbaikinya. Karena itu, gunakan swap sebagai buffer peringatan, lalu perbaiki pengalokasian sumber daya.

Mengapa UFW tidak memblokir port Docker yang dipublikasikan?

Karena trafik tidak pernah mencapai chain yang dijaga UFW. Saat Anda memublikasikan port dengan -p 5432:5432 atau entri compose ports:, daemon menulis aturan DNAT (destination network address translation) ke dalam tabel nat dan aturan accept ke chain DOCKER miliknya sendiri. Paket yang ditujukan ke container diteruskan ke container tersebut, bukan dikirimkan ke host. Karena itu, paket diproses melalui jalur FORWARD dan tidak pernah melewati aturan INPUT yang ditulis UFW.

Anda dapat mengamati proses ini di server:

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

UFW dapat menampilkan 5432 DENY IN Anywhere, sementara tabel nat memiliki aturan DNAT tcp ... to:172.18.0.2:5432 untuk port yang sama. Dari mesin lain, nc -vz your.server.ip 5432 tetap dapat terhubung. Database tersebut berada di Internet publik, tetapi firewall menyatakan bahwa database itu tidak terekspos.

Solusinya adalah mengurangi port yang dipublikasikan. Container dalam satu proyek compose berbagi jaringan dan dapat saling menjangkau menggunakan nama service. Karena itu, database yang hanya melayani aplikasi di sebelahnya tidak memerlukan entri ports: sama sekali. Jika Anda memerlukan akses lokal, bind publikasi tersebut ke loopback:

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

Setelah docker compose up -d, nc -vz your.server.ip 5432 dari luar gagal, sedangkan psql -h 127.0.0.1 -p 5432 pada host tetap berfungsi. Pada stack kecil yang dikonfigurasi dengan baik, hanya reverse proxy yang memublikasikan port, yaitu 80 dan 443. Mengapa port Docker yang dipublikasikan melewati UFW membahas chain DOCKER-USER untuk kasus ketika Anda harus memublikasikan port dan tetap memfilternya, sedangkan Dasar-dasar firewall UFW membahas aturan host yang mendasarinya.

Mengapa container saya hilang setelah reboot?

Karena tidak ada konfigurasi yang memintanya untuk berjalan kembali. Container dibuat dengan kebijakan restart no jika Anda tidak menetapkan kebijakan lain, sehingga reboot membuatnya berhenti dan daemon tidak akan menjalankannya kembali. Reboot bukan kejadian langka pada VPS: pembaruan kernel dari unattended upgrades, pemeliharaan provider, dan rangkaian OOM di atas semuanya dapat mengakhirinya.

Dua hal harus terpenuhi. Daemon harus dijalankan saat boot:

systemctl is-enabled docker

Perintah tersebut menampilkan enabled pada instalasi Ubuntu standar. Kemudian, setiap service memerlukan kebijakan:

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

unless-stopped menjalankan kembali container setelah reboot dan tetap menghormati container yang Anda hentikan secara sengaja. always juga menjalankan kembali container yang Anda hentikan secara sengaja setiap kali daemon dimulai ulang. Hal ini dapat mengejutkan saat proses debugging berlangsung. Mengedit file saja tidak cukup karena kebijakan restart ditetapkan saat container dibuat. Jalankan docker compose up -d agar container dibuat ulang, lalu periksa nilainya saat ini:

docker inspect my-app | grep -A3 RestartPolicy

Kemudian lakukan reboot pada server secara sengaja dan jalankan docker compose ps di direktori project. Stack yang tetap berjalan setelah reboot terencana juga akan tetap berjalan setelah reboot yang tidak terencana. Jika stack Anda memerlukan jaminan urutan atau job sekali jalan saat boot, unit systemd adalah alat yang lebih tepat: menjalankan Docker Compose saat boot memiliki file unit tersebut. Untuk memastikan bahwa container yang berjalan kembali benar-benar melayani permintaan, tambahkan healthcheck Compose.

Mengapa disk VPS saya penuh?

Karena Docker menyimpan semuanya sampai Anda memerintahkannya untuk menghapusnya. Setiap tag image yang pernah Anda pull, setiap container yang dihentikan, setiap anonymous volume yang tertinggal setelah recreate, dan setiap layer build cache tetap tersimpan di disk. Pada root filesystem berukuran 40 GB atau 80 GB, yang umum pada ukuran paket ini, kondisi tersebut dapat menyebabkan outage dalam hitungan bulan, bukan tahun.

Disk penuh tidak terlihat seperti crash. Anda dapat menerima no space left on device dari container, apt, journald, dan docker pull dalam jam yang sama. PostgreSQL berhenti menerima operasi tulis. Server masih aktif, sehingga masalah ini lebih sulit diketahui daripada reboot loop.

Periksa sebelum menghapus:

docker system df
df -h /

docker system df membagi total penggunaan menjadi images, containers, local volumes, dan build cache, dengan kolom RECLAIMABLE di samping masing-masing kategori. Pada server yang membangun image sendiri, build cache biasanya menjadi penggunaan terbesar.

docker image prune -a
docker builder prune
docker system df

docker image prune -a menghapus semua image yang tidak digunakan oleh container mana pun. docker builder prune menghapus build cache. Keduanya aman dijalankan saat service aktif karena item yang sedang digunakan akan dilewati. Yang tidak aman adalah docker system prune --volumes, yang menghapus setiap volume yang saat ini tidak direferensikan oleh container mana pun. Stack yang Anda hentikan selama akhir pekan memiliki kondisi tersebut, dan volume database-nya ikut terhapus. Baca bind mounts versus named volumes sebelum menggunakan flag tersebut, dan buat backup terlebih dahulu.

Log container menyebabkan pertumbuhan yang lebih sulit terlihat. Driver default json-file tidak memiliki batas ukuran, sehingga satu container yang banyak menghasilkan log dapat menulis gigabyte ke dalam /var/lib/docker/containers. Tetapkan batas untuk setiap container di /etc/docker/daemon.json:

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

Terapkan perubahan tersebut dengan sudo systemctl restart docker. Perintah ini akan me-restart container Anda, jadi pilih waktunya dengan tepat. Batas tersebut berlaku untuk container yang dibuat setelah perubahan. Karena itu, buat ulang container yang sedang berjalan dengan docker compose up -d --force-recreate lalu konfirmasikan:

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

Output inspect harus menampilkan max-size. Jika nilainya kosong, container tersebut dibuat sebelum perubahan dan masih menulis tanpa batas.

Kebiasaan untuk menjaga Docker box kecil tetap sehat

Semua ini tidak memerlukan dashboard atau alat yang harus Anda pelajari.

  • Jalankan docker system df dan df -h / pada tanggal 1 setiap bulan. Dua perintah, tiga puluh detik, dan Anda dapat melihat trennya jauh sebelum berubah menjadi outage.
  • Tetapkan batas memori untuk setiap service, termasuk service yang Anda yakin berukuran kecil. Batas ini mengubah outage pada seluruh host menjadi satu container yang di-restart.
  • Pantau box dari lokasi lain agar Anda mengetahui tekanan memori atau disk sebelum kernel bertindak. Uptime Kuma berjalan dalam container dan menggunakan sekitar 95 MB saat idle.
  • Cadangkan volume, bukan container. Container dapat dibuang, sedangkan volume tidak. backup restic pada VPS mencakup jadwal dan pengujian restore.
  • Tetapkan tag image pada file compose dan perbarui tag tersebut pada hari yang Anda pilih. Dengan latest, versi yang Anda dapatkan dari docker compose pull berikutnya adalah versi yang dirilis pagi itu.

VPS kecil yang menjalankan Docker dapat tetap sehat selama bertahun-tahun jika empat angka tetap dalam batas: anggaran memori, daftar port yang dipublikasikan, kebijakan restart setiap service, dan ruang disk yang tersedia. Selebihnya adalah Docker yang sama seperti yang sudah Anda jalankan di rumah.

FAQ

Berapa banyak RAM yang saya perlukan untuk menjalankan Docker pada VPS?

Docker sendiri tidak membutuhkan banyak sumber daya. Daemon dan containerd secara keseluruhan menggunakan sekitar 100 MB, sedangkan kebutuhan lainnya ditentukan oleh container Anda. Alokasikan terlebih dahulu porsi untuk host: 768 MB pada server dengan 2048 MB untuk sistem operasi, daemon, dan ruang cadangan. Dengan demikian, tersedia 1280 MB untuk container. Database sebesar 512 MB, reverse proxy sebesar 128 MB, dan dua aplikasi kecil dapat berjalan dalam batas tersebut. Ukur stack Anda sendiri dengan docker stats --no-stream, bukan berdasarkan angka yang dipublikasikan.

Apakah saya dapat menjalankan Docker pada VPS 1 GB?

Ya, untuk satu atau dua container ringan. Buat swap file sebelum memulainya. Sekitar setengah kapasitas server 1 GB sudah terpakai setelah sistem operasi dan Docker daemon berjalan. Sisa kapasitasnya cukup untuk aplikasi kecil dan reverse proxy, tetapi tidak cukup untuk database yang menerima beban nyata. Proses build image pada server dengan kapasitas tersebut dapat gagal atau menghentikan proses lain. Karena itu, lakukan build di tempat lain lalu pull image yang sudah selesai.

Apakah UFW melindungi container Docker?

Tidak untuk port yang Anda publish. Docker menulis aturan DNAT dan forward sendiri. Karena itu, paket yang ditujukan ke port container yang dipublikasikan akan diteruskan ke container, bukan dikirimkan ke host. Aturan INPUT yang dikelola UFW tidak akan melihat paket tersebut. ufw deny 5432 dapat tetap aktif meskipun port itu merespons dari Internet. Gunakan 127.0.0.1:5432:5432 untuk publish ke loopback, jangan publish service internal, atau lakukan filtering pada chain DOCKER-USER.

Apakah container saya akan restart setelah VPS reboot?

Hanya jika container dibuat dengan restart policy. Tetapkan restart: unless-stopped pada setiap service, jalankan docker compose up -d agar container dibuat ulang dengan pengaturan tersebut, lalu pastikan systemctl is-enabled docker menampilkan enabled. Setelah itu, lakukan reboot secara sengaja dan periksa docker compose ps. Restart policy yang belum pernah diuji bukanlah restart policy yang dapat diandalkan.

Seberapa sering saya harus melakukan prune image Docker?

Sebulan sekali sudah cukup untuk sebagian besar server kecil. Anda juga dapat melakukannya setiap kali docker system df melaporkan ruang yang dapat diperoleh kembali dan ruang tersebut Anda perlukan. docker image prune -a dan docker builder prune aman dijalankan saat service aktif karena image dan cache yang sedang digunakan akan dilewati. Hindari docker system prune --volumes kecuali Anda benar-benar mengetahui volume mana yang tidak memiliki referensi, karena perintah tersebut menghapus data dari stack yang kebetulan sedang berhenti.