Healthcheck Docker, Cara Container Tahu Dirinya Sehat
Healthcheck membuat Docker tahu apakah aplikasi di dalam container benar-benar melayani, bukan sekadar prosesnya hidup. Begini cara menulis dan membacanya.
Jawaban singkat
Healthcheck adalah perintah kecil yang dijalankan Docker berkala di dalam container. Bila perintah itu gagal beberapa kali berturut-turut, status container berubah menjadi unhealthy, sehingga kamu, Compose, atau alat pemantau bisa bereaksi sebelum pengguna mengeluh.
Daftar isi
Bayangkan container aplikasi web yang statusnya Up 3 days di docker ps, tapi setiap request ke situsmu berakhir dengan error 502. Prosesnya memang masih hidup, hanya saja aplikasinya macet, kehabisan koneksi database, atau terjebak di loop. Dari sudut pandang Docker, semuanya baik-baik saja.
Healthcheck menutup celah itu. Kamu memberi Docker satu perintah untuk menguji apakah aplikasi benar-benar melayani, misalnya memanggil endpoint /health. Docker menjalankannya berkala, lalu menandai container sebagai healthy atau unhealthy. Status inilah yang bisa dipakai untuk urutan start di Compose, pemantauan, dan keputusan restart.
Proses hidup belum tentu aplikasi sehat
Tanpa healthcheck, satu-satunya yang Docker ketahui adalah apakah proses utama (PID 1 di dalam container) masih berjalan. Kalau proses itu keluar, Docker tahu dan bisa menjalankan ulang sesuai restart policy. Tapi banyak kegagalan tidak membuat proses keluar: thread pool penuh, deadlock, koneksi ke database putus dan tidak pulih, atau disk penuh sehingga aplikasi menolak menulis.
Healthcheck menjawab pertanyaan yang lebih berguna, yaitu "apakah layanan ini bisa dipakai sekarang?". Perintahnya dijalankan di dalam container, jadi ia melihat aplikasi dari dekat, tanpa terpengaruh firewall atau reverse proxy di luar.
Aturannya sederhana. Perintah yang keluar dengan kode 0 berarti sehat, kode 1 berarti tidak sehat. Kode 2 dicadangkan oleh Docker dan sebaiknya tidak dipakai.
Menulis healthcheck di Dockerfile
Healthcheck bisa ditanam langsung di image lewat instruksi HEALTHCHECK. Contoh untuk aplikasi web yang mendengarkan port 8080:
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
CMD curl -fsS http://localhost:8080/health || exit 1
Opsi -f pada curl membuat respons HTTP 4xx dan 5xx dianggap gagal, sedangkan || exit 1 memastikan kode keluarnya selalu 1 saat gagal. Setiap image hanya boleh punya satu HEALTHCHECK. Kalau ada lebih dari satu, yang terakhir yang berlaku. Image turunan bisa mematikan healthcheck warisan dengan HEALTHCHECK NONE.
Satu hal yang sering terlupa: image ramping (berbasis Alpine, distroless, atau slim) sering tidak membawa curl. Pilihannya memasang curl atau wget saat build, memakai perintah bawaan aplikasi (misalnya pg_isready di image PostgreSQL atau redis-cli ping di image Redis), atau menulis skrip pengecek kecil dalam bahasa yang memang sudah ada di image.
Berikut arti setiap opsi beserta nilai bawaannya menurut dokumentasi Docker:
| Opsi | Fungsi | Bawaan |
|---|---|---|
--interval | Jeda antar pengecekan | 30 detik |
--timeout | Batas waktu satu pengecekan, lewat dari ini dianggap gagal | 30 detik |
--start-period | Masa pemanasan, kegagalan di masa ini tidak dihitung | 0 detik |
--start-interval | Jeda pengecekan selama masa pemanasan (Docker Engine 25 ke atas) | 5 detik |
--retries | Jumlah gagal berturut-turut sebelum dinyatakan unhealthy | 3 |
Dengan nilai bawaan, container baru dinyatakan unhealthy setelah tiga kali gagal berturut-turut, jadi butuh sekitar satu setengah menit. Untuk layanan yang penting, interval lebih pendek dengan timeout yang realistis biasanya lebih pas.
Healthcheck di Docker Compose
Kalau image dibuat orang lain dan kamu tidak ingin mengubah Dockerfile, healthcheck bisa ditulis di compose.yaml. Nilai di sini menimpa healthcheck yang tertanam di image.
services:
db:
image: postgres:17
environment:
POSTGRES_PASSWORD: rahasia
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
app:
image: contoh/app:latest
depends_on:
db:
condition: service_healthy
Bagian depends_on dengan condition: service_healthy adalah manfaat terbesar healthcheck di Compose. Tanpa itu, Compose hanya menunggu container database dibuat, bukan menunggu PostgreSQL siap menerima koneksi. Hasilnya aplikasi sering gagal saat start pertama karena database belum siap. Dengan healthcheck, app baru dijalankan setelah db berstatus healthy.
Bentuk CMD menjalankan perintah langsung tanpa shell, sedangkan CMD-SHELL menjalankannya lewat /bin/sh -c sehingga operator seperti || dan variabel lingkungan bisa dipakai.
Membaca status kesehatan container
Status kesehatan tampil di kolom STATUS pada docker ps, misalnya Up 2 minutes (healthy). Ada tiga kemungkinan: starting selama masa pemanasan, healthy, dan unhealthy.
Untuk melihat riwayat pengecekan lengkap dengan keluaran perintahnya:
docker inspect --format '{{json .State.Health}}' nama-container
Hasilnya berisi status, jumlah kegagalan berturut-turut, dan beberapa log pengecekan terakhir. Bagian log ini sangat membantu saat healthcheck gagal karena hal sepele, misalnya port salah atau curl tidak ada di image.
Apakah Docker otomatis me-restart container yang unhealthy?
Di Docker Engine biasa (tanpa Swarm), jawabannya tidak. Status unhealthy hanya sebuah label. restart: always atau unless-stopped hanya bereaksi saat proses utama keluar, bukan saat healthcheck gagal. Di mode Swarm, task yang unhealthy akan diganti oleh orkestrator.
Jadi di VPS tunggal, kamu perlu sesuatu yang membaca status itu. Pilihannya antara lain alat pemantau yang memberi notifikasi, skrip kecil yang dijalankan berkala untuk me-restart container berstatus unhealthy, atau membuat aplikasi keluar sendiri saat mendeteksi kondisi rusak sehingga restart policy yang bekerja. Kalau kamu sudah memakai Uptime Kuma, endpoint kesehatan yang sama juga bisa dipantau dari luar.
Rancang endpoint kesehatan yang jujur
Healthcheck hanya sebaik perintah yang diuji. Endpoint /health yang selalu menjawab "OK" tanpa memeriksa apa pun tidak memberi informasi. Sebaliknya, endpoint yang memeriksa terlalu banyak hal (misalnya API pihak ketiga) bisa membuat container dianggap sakit padahal masalahnya di luar kendalimu.
Patokan yang masuk akal: periksa hal yang memang dibutuhkan aplikasi untuk melayani, seperti koneksi database dan kemampuan menulis ke disk, dengan query yang ringan. Jaga agar pengecekan selesai jauh di bawah nilai timeout, karena healthcheck yang lambat ikut membebani server. Hindari juga perintah yang meninggalkan file sementara atau koneksi menggantung di setiap putaran.
Healthcheck cocok dipadukan dengan praktik lain di kesalahan umum Docker di produksi dan pembatasan CPU serta RAM container, supaya satu container yang bermasalah tidak menyeret seluruh server.
Intinya, healthcheck mengubah "prosesnya masih jalan" menjadi "layanannya bisa dipakai". Tulis di Dockerfile atau Compose, pakai service_healthy untuk urutan start, lalu pastikan ada yang benar-benar membaca status unhealthy, karena Docker biasa tidak akan bertindak sendiri.


