Banyak developer pake Docker HEALTHCHECK dan mikir: "Kalau healthcheck return healthy, berarti container lo aman." Salah besar. HEALTHCHECK cuma ngecek satu hal: apakah proses di dalam container merespon. Itu aja. Bukan ngecek apakah API lo jalan dengan bener. Bukan ngecek apakah database bisa di-query. Bukan ngecek apakah response time masih normal.
Ini realitas yang sering terjadi: production server return 200 OK di healthcheck endpoint — tapi aplikasi balikin empty response buat semua request user. Butuh 30 menit buat debug karena healthcheck bilang "semua baik-baik aja". Healthcheck yang cuma ngecek "apakah proses hidup?" itu bohong.
Artikel ini breakdown: apa yang HEALTHCHECK sebenarnya ukur, di mana lo overestimate, dan gimana cara yang benar untuk monitoring container di production.
Apa yang HEALTHCHECK Ukur (dan Gak Ukur)
Docker HEALTHCHECK secara default ngejalanin command di dalam container. Kalau exit code 0 → healthy. Exit code 1 → unhealthy. Itu aja. Gak ada magic.
Yang DIUKUR:
- Apakah proses utama (PID 1) masih berjalan?
- Apakah port TCP yang di-expose merespon koneksi?
- Apakah endpoint HTTP yang lo define return 200?
Yang TIDAK diukur:
- Apakah response time masih normal? (Bisa 200 OK tapi butuh 30 detik)
- Apakah data yang di-return benar? (Empty response juga bisa return 200)
- Apakah background job masih jalan? (Healthcheck cuma ngecek main process)
- Apakah koneksi ke database masih hidup? (API bisa 200 tapi DB disconnected)
- Apakah memory leak? (Proses masih hidup tapi OOM tinggal 5 menit lagi)
Ibaratnya: HEALTHCHECK itu kayak ngecek apakah mobil lo idup — tapi gak ngecek apakah mesinnya misfire, bensin mau abis, atau rodanya copot.
Contoh Kasus: HEALTHCHECK yang Menipu
Ini Dockerfile yang umum dipake:
FROM node:20-alpine
COPY . /app
HEALTHCHECK --interval=30s --timeout=3s --retries=3 CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD ["node", "server.js"]
Masalah: endpoint /health return 200 karena server jalan — tapi database connection pool-nya abis, jadi semua request user return 503. Healthcheck gak nangkep.
Real example: suatu waktu ada memory leak di Node.js event loop. Proses masih jalan, healthcheck return 200 — tapi memory usage naik 200MB per jam. Container restart automatis dari --restart unless-stopped gak pernah triggered karena healthcheck selalu OK. Akhirnya server crash total setelah 6 jam — dan kita baru sadar pas user komplen.
Membuat HEALTHCHECK yang Bermakna
Solusinya: healthcheck harus ngecek dependensi, bukan cuma ngecek "apakah proses idup". Ini contoh yang lebih meaningful:
# Di container API Node.js
HEALTHCHECK --interval=15s --timeout=5s --start-period=30s --retries=2 CMD node -e "
const http = require('http');
const req = http.get('http://localhost:3000/api/health', (res) => {
let data = '';
res.on('data', (chunk) => data += chunk);
res.on('end', () => {
const json = JSON.parse(data);
// Cek BUKAN cuma status, tapi juga dependensi
if (json.status === 'ok' &&
json.database === 'connected' &&
json.redis === 'connected' &&
json.responseTime < 2000) {
process.exit(0); // Healthy
}
process.exit(1); // Unhealthy
});
});
req.on('error', () => process.exit(1));
req.setTimeout(5000, () => process.exit(1));
"
Endpoint /api/health di aplikasi harus report status semua dependensi:
// Express.js health endpoint
app.get('/api/health', async (req, res) => {
const checks = {
status: 'ok',
database: await checkDatabase(),
redis: await checkRedis(),
diskSpace: checkDisk(),
memoryUsage: process.memoryUsage().heapUsed / 1024 / 1024,
uptime: process.uptime(),
responseTime: 0
};
// Hitung response time endpoint ini sendiri
const start = Date.now();
checks.responseTime = Date.now() - start;
// Overall status
const unhealthy = Object.values(checks)
.filter(v => typeof v === 'string')
.some(v => v !== 'ok' && v !== 'healthy');
res.status(unhealthy ? 503 : 200).json(checks);
});
Dengan setup ini, healthcheck bisa nangkep: (1) database disconnect, (2) Redis down, (3) memory hampir penuh, (4) response time lambat. Bukan cuma "server hidup atau mati."
Decision Matrix: Kapan HEALTHCHECK Cukup?
| Use Case | Simple HEALTHCHECK | Deep healthcheck | External monitoring |
|---|---|---|---|
| Static website (nginx) | ✅ Cukup | ❌ Overkill | ❌ Overkill |
| API dengan database | ❌ Gak cukup | ✅ Recommended | ✅ Pelengkap |
| Background worker | ❌ Gak cukup | ✅ (cek queue) | ✅ (cek output) |
| Database container | ✅ Cukup | ❌ Overkill | ✅ Recommended |
| Microservice (production) | ❌ Gak cukup | ✅ Wajib | ✅ Wajib |
| Cron job container | ❌ Gak relevan | ❌ Gak relevan | ✅ (cek hasil job) |
HEALTHCHECK vs External Monitoring
Poin penting dari semua ini: HEALTHCHECK bukan pengganti external monitoring. HEALTHCHECK berguna buat Docker orchestration (swarm, kubernetes) buat nentuin kapan container perlu di-restart. Tapi buat alerting dan observability, lo butuh external monitoring:
- Uptime Kuma atau Better Uptime: Ngecek dari luar server — bisa deteksi masalah yang gak kelihatan dari dalam container (misal: firewall block, DNS failure, CDN issue). Di artikel self-hosted analytics kita bahas tools serupa.
- Prometheus + Grafana: Metrics-based monitoring. Bikin dashboard yang nunjukkin: request rate, error rate, latency p95, memory usage. Kalau ada anomaly, langsung alert.
- Structured logging: Kayak yang kita bahas di ELK Stack vs Loki — centralized logging biar lo bisa search error history dengan cepat.
Rule of thumb dari gw: setiap container harus punya HEALTHCHECK yang ngecek dependensi langsung-nya, DAN tiap service harus di-monitor dari luar. HEALTHCHECK = internal circuit breaker. External monitoring = smoke detector. Lo butuh keduanya.
HEALTHCHECK Parameter yang Tepat
Gw sering liat orang asal copy HEALTHCHECK dari tutorial tanpa adjust parameter. Ini parameter yang gw gunakan berdasarkan type container:
# API server (Node.js, Go, Python)
HEALTHCHECK --interval=15s --timeout=5s --start-period=30s --retries=3 CMD curl -f http://localhost:3000/api/health || exit 1
# interval=15s: cepet deteksi masalah
# start-period=30s: kasih waktu startup (migration, cache warmup)
# retries=3: 3x gagal sebelum dianggep unhealthy (45s total)
# Background worker
HEALTHCHECK --interval=60s --timeout=10s --start-period=60s --retries=2 CMD /healthcheck/check-worker.sh || exit 1
# interval=60s: worker gak perlu di-cek tiap 15 detik
# start-period=60s: worker butuh waktu buat connect queue
# Database (Postgres)
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=5 CMD pg_isready -U postgres || exit 1
# retries=5: database bisa flapping pas restart — jangan buru-buru dianggep mati
Satu hal lagi: jangan pake curl di Alpine-based image. Alpine pake BusyBox yang curl-nya limited. Pake wget --spider atau install curl dari apt/apk. Atau lebih baik: pake node -e atau python -c — lebih reliable karena lo udah punya runtime di container.
Buat strategi container security yang lebih comprehensive, baca Container Security Hardening — termasuk cara setup read-only filesystem dan drop capabilities yang bisa ngebantu healthcheck lebih efektif.
💬 Komentar (0)
Belum ada komentar. Jadilah yang pertama! 💬