DEV Community

Sohana Akbar
Sohana Akbar

Posted on

Health Checks in Docker — Why Your Frontend Container Needs Them

Let’s be honest: when you first heard about HEALTHCHECK in Docker, you probably thought, “That’s for databases and backend APIs. My React/Vue/Svelte app just serves static files. It’s either up or it’s not.”

I thought the same thing. Until a silent production outage taught me otherwise.

Here’s why your frontend container deserves a health check just as much as your Postgres or Node.js API — and how to implement it in under 5 minutes.

The Myth: “Static = Unbreakable”
We treat frontend containers like dumb file servers. After all, nginx serving an index.html either runs or crashes, right?

But “running” isn’t the same as “healthy.”

Consider these real-world scenarios:

Your build pipeline failed — the container started, but index.html is missing.

Environment variables didn’t inject — your JS app loads, but API calls go to undefined.

Nginx misconfiguration — the container is alive but returns 500 on every route.

Asset caching gone wrong — your users see a white screen due to broken chunk loading.

Without a health check, Docker Swarm or Kubernetes thinks: “Process is alive? Great, keep sending traffic.”

Why Orchestrators Need More Than “Process Running”
Docker’s default health status is a lie of omission. If the CMD or ENTRYPOINT runs, the container is marked started. Not healthy. Just… existing.

But orchestrators like Docker Swarm, Kubernetes, or even docker-compose with restart: always rely on health checks to make decisions:

Rolling updates — replace old containers only when new ones are truly ready.

Auto-healing — kill and recreate containers that fail health checks.

Load balancing — route traffic only to healthy instances.

A frontend container with a missing index.html passes the “process alive” test. Your orchestrator happily sends users to a white screen of death.

The $PATH to Redemption: A Simple Health Check
The fix is embarrassingly simple. Add a HEALTHCHECK to your Dockerfile:

dockerfile
FROM nginx:alpine

COPY dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost/ || exit 1
Or, if you’re not using curl (Alpine includes wget by default):

dockerfile
HEALTHCHECK CMD wget --no-verbose --tries=1 --spider http://localhost/ || exit 1
Here’s what those flags mean:

Flag Value Why
--interval 30s Don’t overwhelm your container
--timeout 3s Fail fast if something hangs
--start-period 5s Give nginx time to boot
--retries 3 Avoid flapping from transient failures
Beyond “Is the Server Up?” — Smarter Checks
The example above verifies nginx is serving something. But you can (and should) go further:

Check that your actual HTML exists:

dockerfile
HEALTHCHECK CMD curl -f http://localhost/index.html || exit 1
Validate that environment variables were injected correctly:

dockerfile
HEALTHCHECK CMD curl -f http://localhost/settings.js | grep "API_URL=https://prod" || exit 1
For SPAs, check that critical assets load:

dockerfile
HEALTHCHECK CMD curl -f http://localhost/static/js/main.*.js || exit 1
Simulate a user flow (advanced, but powerful):

dockerfile
HEALTHCHECK CMD curl -s http://localhost/ | grep "Welcome to MyApp" || exit 1
Real-World Impact: A Debugging Story
Last month, our CI pipeline silently failed during the COPY dist step (disk full). The container started. Nginx ran. Docker said Up 2 minutes.

But dist was empty.

Without a health check: users saw a blank page for 45 minutes before someone noticed.

With a health check: after 30 seconds, container status became unhealthy. Swarm killed it, tried to spin up a new one (same broken image), and alerted us immediately via the Docker event stream.

We fixed the pipeline in 10 minutes instead of losing an hour of user trust.

How to See Health Status
Check manually:

bash
docker ps

CONTAINER ID STATUS

a1b2c3 Up 2 minutes (healthy)

docker inspect | jq '.[].State.Health'
Or with docker-compose:

yaml
services:
frontend:
build: .
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 3s
retries: 3
Now docker-compose ps will show healthy instead of just up.

When You Might NOT Need It
Honestly? Almost always want one. But exceptions exist:

Local development only — you’re not orchestrating anything.

Static site on a CDN — your container isn’t serving traffic directly.

Extremely ephemeral containers (e.g., batch jobs that exit immediately).

For anything that sits behind a load balancer or runs in production? Add the damn health check.

Go Make Your Frontend Containers Self-Aware
Your frontend is not dumb static baggage. It’s the face of your application. When it fails, users notice immediately — not your database, not your API.

Give Docker the ability to know the difference between “I’m alive” and “I’m actually working.”

Add that HEALTHCHECK today. Future you (and your users) will thank you.

Have you debugged a frontend container failure that a health check would’ve caught? Share your war story in the comments!

Top comments (0)