Healthchecks: The Pulse of your Application

A container can be Running (PID 1 exists) but Broken (Deadlock, infinite loop, database connection lost). To Docker, everything looks fine because the process is still there. To your users, the site is down.

1. The HEALTHCHECK Instruction

You can teach Docker how to test your application.

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost/healthz || exit 1
  • interval: How often to run the check.
  • timeout: If the check takes longer than this, it fails.
  • start-period: Grace period for the app to boot up (failures here are ignored).
  • retries: How many consecutive failures before marking the container unhealthy.

2. Interactive: Health Probe Simulator

Simulate a production scenario. Break the app and watch how Docker detects the failure after the configured retries.

Docker Daemon
Idle
My App
healthy
Retries Failed: 0 / 3

3. Code Example: Implementing /healthz

Your application needs to expose an endpoint that returns HTTP 200 only if the app is truly ready to accept traffic.

Spring Boot provides this out-of-the-box with Spring Boot Actuator.

  1. Add dependency: spring-boot-starter-actuator
  2. Configure application.properties:
management.endpoints.web.exposure.include=health
management.endpoint.health.probes.enabled=true

Result: Docker can poll http://localhost:8080/actuator/health.

In Go, you implement a simple handler.

package main

import (
    "database/sql"
    "fmt"
    "net/http"
)

var db *sql.DB

func healthHandler(w http.ResponseWriter, r *http.Request) {
    // 1. Check DB connection
    if err := db.Ping(); err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        w.Write([]byte("Unhealthy: DB Down"))
        return
    }

    // 2. Success
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("OK"))
}

func main() {
    http.HandleFunc("/healthz", healthHandler)
    http.ListenAndServe(":8080", nil)
}