Membatasi Resource Container Supaya Tidak Saling Rebutan
Saya sudah beberapa kali menemukan pola yang sama di stack Docker: satu container yang harusnya ringan tiba-tiba menghabiskan hampir seluruh CPU host, dan container lain jadi lemot padahal beban kerjanya sendiri tidak naik. Ini bukan soal salah satu container "rusak", tapi soal tidak ada batas yang jelas siapa boleh pakai berapa. Tanpa limit, Docker akan membiarkan container berebut resource host secara bebas, dan yang paling rakus akan menang — apapun prioritas bisnisnya.
Masalahnya, kebanyakan tim (termasuk saya di masa awal pakai Docker) menyelesaikan ini dengan cara yang salah: comot angka limit dari contoh di internet atau dari template docker-compose.yml orang lain, tanpa melihat beban aktual aplikasi sendiri. Hasilnya dua ekstrem yang sama-sama merugikan: limit terlalu longgar sehingga percuma dipasang, atau terlalu ketat sehingga aplikasi sendiri yang throttling dan lambat.
Kenapa Angka Default (atau Tebak-tebakan) Itu Jebakan
Angka default biasanya dibuat generik supaya "aman" untuk banyak kasus, bukan optimal untuk kasus spesifik. Container PHP-FPM untuk aplikasi Laravel yang menangani banyak query database punya profil beban yang sangat berbeda dari container worker queue yang jarang aktif tapi sesekali memproses job berat. Kalau keduanya dipasang limit yang sama karena "biar gampang", salah satu pasti akan under-provisioned atau over-provisioned.
Efek sampingnya juga sering tidak terlihat langsung. Container yang di-throttle CPU-nya tidak selalu crash — dia hanya jadi lambat, request menumpuk, dan kalau tidak ada monitoring yang jeli, gejala ini gampang disalahartikan sebagai bug aplikasi atau masalah database, padahal akar masalahnya di layer orchestration.
Ukur Beban Nyata Dulu, Baru Tentukan Limit
Sebelum menulis angka apapun di deploy.resources, saya selalu mengumpulkan data pemakaian riil dulu, minimal dalam kondisi beban normal dan beban puncak. Cara paling sederhana ya pakai docker stats untuk melihat snapshot langsung, atau kalau mau lebih jangka panjang, arahkan metrik container ke tool monitoring (cAdvisor, Prometheus, atau bahkan dashboard bawaan Docker Desktop) supaya kelihatan pola pemakaian dari waktu ke waktu, bukan cuma satu titik waktu.
Yang saya cari dari data ini bukan angka rata-rata saja, tapi juga puncaknya. Sebagai ilustrasi, kalau rata-rata pemakaian memori sebuah container ada di kisaran 300MB tapi sesekali melonjak ke 700MB saat ada proses import data, maka limit yang dipasang harus mengakomodasi lonjakan itu, bukan cuma rata-ratanya — kalau tidak, container akan di-kill oleh OOM killer tepat saat sedang dibutuhkan.
Menentukan Angka yang Realistis
Setelah punya gambaran beban, saya biasanya memberi ruang di atas puncak yang teramati, bukan pas-pasan. Untuk memory, saya set limit dengan buffer yang cukup longgar di atas puncak pemakaian normal, supaya lonjakan sesaat tidak langsung mematikan proses. Untuk CPU, saya lebih suka mikirkan dalam satuan "berapa banyak core yang benar-benar dipakai", bukan persentase abstrak.
Contoh konfigurasi di docker-compose.yml yang biasa saya pakai sebagai titik awal:
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M
reservations:
cpus: "0.25"
memory: 256M
Perlu dicatat, kunci deploy.resources ini asalnya dari dunia Docker Swarm, jadi pastikan kamu pakai Docker Compose versi baru (perintah docker compose, bukan docker-compose versi lama) supaya limit-nya benar-benar diterapkan meski tidak jalan di mode Swarm.
reservations juga sering disalahpahami. Ini bukan jaminan keras seperti limits, melainkan lebih ke pedoman minimum resource — paling terasa dampaknya kalau kamu jalan di orchestrator dengan banyak node (Swarm, Kubernetes) yang punya scheduler untuk mengalokasikan resource antar node. Di single host tanpa orchestrator seperti itu, yang benar-benar ditegakkan secara keras oleh cgroups adalah limits; jadi kalau tujuan utamanya memastikan container tidak saling rebutan resource host, fokuslah dulu ke angka limits yang realistis, baru anggap reservations sebagai dokumentasi niat.
Angka-angka ini juga bukan sekali tulis lalu selesai. Tiap kali ada perubahan pola trafik yang cukup signifikan — misalnya penambahan fitur baru yang lebih berat di query database — saya ulang lagi proses pengukurannya. Limit yang cocok enam bulan lalu belum tentu masih cocok sekarang.
Takeaway
Intinya sederhana: jangan pasang limit CPU/memory berdasarkan tebakan atau contoh yang dicopy dari tempat lain. Ukur dulu beban nyata masing-masing container, beri buffer yang wajar di atas puncaknya, lalu pakai limits sebagai batas keras dan reservations sebagai pedoman tambahan, supaya semua container punya jatah yang jelas dan tidak saling rebutan resource host secara diam-diam.