27 September 2026

Container Up. Application Down.

A running Docker container doesn’t always mean the application is working.

One confusing situation you encounter when working with Docker is running docker ps and seeing that everything looks fine, yet when you open the application, you get a connection error: 502 Bad Gateway. How can the container be running while the application is down? The answer is simple: a running container does not necessarily mean a working application.

docker ps

CONTAINER       STATUS
web             Up 3 hours
nginx           Up 3 hours
postgres        Up 3 hours

What “Running” Actually Means

When Docker reports a container as “Up,” it primarily tells us that the container’s main process (PID 1) is still running. That’s useful information, but it doesn’t tell the whole story. Imagine a Django application running with Gunicorn. The container itself might be running, but Gunicorn may not be serving requests correctly. Or Gunicorn might be fine, but Django cannot connect to PostgreSQL. Or Django may be working perfectly, but Nginx cannot reach Gunicorn. From the user’s perspective, the result is exactly the same: the application is down.

Where I Start

When this happens, I don’t treat docker ps as proof that the application is healthy; it is only my first check.

Next, I look at the application logs using docker logs, and then I check whether the application is actually listening on the expected port inside the container.

# Inspect application logs
docker logs <container_name_or_id>

# Verify if the container is listening on the expected port
docker exec -it <container_name_or_id> netstat -tulpn
# Or check connection directly from the host
curl -I http://localhost:<port>

If the application itself appears healthy, I move outward. Can Nginx reach the application? Can the application reach its database? Are the expected environment variables present? Did something change during the latest deployment? The goal is to isolate exactly where the request stops working.

Don’t Restart Everything Immediately

There is always a temptation to immediately restart everything when an application fails.

# The temptation to bypass debugging
docker restart <container_name_or_id>

Sometimes a quick restart works, but it can also hide the actual problem. If restarting fixes the application without you understanding why it failed in the first place, the same problem will likely return. Logs, container states, and the failing requests themselves contain the evidence needed to understand what happened. I prefer to inspect that evidence before changing the system’s state.

Container Health Is Not Application Health

This distinction becomes critically important when designing monitoring systems. A basic health check might only tell us that the process is alive. A better health check asks if the application can actually serve a real request. Depending on the complexity of your stack, you may need to go further and ask whether it can reach the auxiliary services required to do its job. These are completely different levels of health, which is why seeing an “Up” status shouldn’t end an investigation; it should only tell us where to start.

The Lesson

Ultimately, containers give us an excellent way to package and run software, but the container itself is not the application experience. A container can be running, a process can be alive, and yet the application can still be completely unusable. When production is failing, I try to answer a much more useful question than “Is the container running?” I ask: “Can the application do what the user expects it to do?” That small distinction changes how you troubleshoot, how you monitor, and ultimately, how you build more reliable systems.