MeatButton

Docker Container Keeps Restarting: Why It Crashes and How to Stop the Loop

For anyone whose Docker deployment isn't staying up

Your container starts. It runs for a few seconds. Then it stops. Docker starts it again. It stops again. You check docker ps and see "Restarting (1)" or the status flipping between "Up 2 seconds" and "Exited." You've been watching this for twenty minutes and nothing has changed.

This is called a crash loop, and it's one of the most common Docker problems. Here's what's actually going on.

What's happening, in plain English

A Docker container is a box that your app runs inside. The box itself is fine. The problem is that the app inside the box keeps crashing.

When the app crashes, the box has nothing to run, so it stops. But Docker has a setting called a "restart policy" that says "if the box stops, start it again." So Docker starts the box, the app crashes, the box stops, Docker starts the box, the app crashes...

This is the loop. Docker is doing exactly what you told it to do. The problem isn't Docker. The problem is whatever is making your app crash the moment it starts up.

The most common causes

1. The app crashes on startup

This is by far the most common reason. Your app tries to start, immediately hits something it can't handle, and exits. The usual suspects:

2. Out of memory

If your container has a memory limit (set in your docker-compose file or with --memory), and your app tries to use more than that, Docker kills it instantly. No graceful shutdown, no error message in your app's logs. Just dead.

The clue: The exit code is 137. That's Docker's way of saying "I killed this because it used too much memory."

3. Wrong base image or missing dependencies

Your Dockerfile starts with FROM node:18-alpine or FROM python:3.11-slim. These are stripped-down versions of Linux. They're small and fast, but they might be missing things your app needs — a system library, a specific tool, a C compiler that one of your packages requires.

The app builds fine. It even starts. Then it tries to use the missing thing and crashes.

4. Port conflicts

Two containers can't use the same port on the host machine. If another container (or another service on the host) is already using port 3000, and your container tries to bind to port 3000, it fails. Some apps handle this gracefully. Many don't.

5. Volume and permission issues

Your container tries to write to a directory — maybe for logs, uploads, or a database file. But the directory doesn't exist inside the container, or the user the container is running as doesn't have permission to write there. The app crashes the moment it tries to save anything.

How to find the actual problem

The loop is a symptom. Here's how to find the cause.

Read the logs

Run docker logs your-container-name. This shows you what the app printed before it crashed. The answer is almost always in here. Read the last 20-30 lines carefully. Look for error messages, stack traces, or the word "fatal."

If the container keeps restarting and the logs are hard to read, add --tail 50 to see just the last 50 lines, or --since 2m to see only the last 2 minutes.

Check the exit code

Run docker inspect your-container-name --format='{{.State.ExitCode}}'. The exit code tells you how the app died:

Run it interactively

Instead of letting Docker restart the container in the background, run it yourself so you can watch it die in real time:

docker run -it your-image-name

This starts the container in the foreground with your terminal attached. You'll see exactly what happens from the moment it starts until the moment it crashes. No restart loop, no guessing.

Check your environment variables

Open your docker-compose.yml or your docker run command. Look at every environment variable. Then look at what your app actually expects. These need to match. A missing DATABASE_URL or a misspelled STRIPE_SECRET_KEY will crash your app before it serves a single request.

Why AI is bad at debugging this

AI can generate a Dockerfile. It's pretty good at it, actually. The problem is that a Dockerfile that builds successfully is not the same as a Dockerfile that runs successfully. Building means "can I assemble this box?" Running means "does the app inside the box actually work in this specific environment?"

AI doesn't know your environment. It doesn't know what database you're running, what port is already taken, what version of Node is installed on the host, or whether the volume mount you need actually exists. It generates something generic and hopes it works.

The classic AI Docker mistake

This one happens constantly: AI generates a Dockerfile that builds perfectly. You run the container. It crashes. The reason? The app inside tries to connect to localhost to reach the database.

On your laptop, that works. Inside a Docker container, localhost means the container itself — not your computer, not the database server, not anything useful. The app can't find the database, throws a connection error, and exits.

AI does this because it learned from tutorials where everything runs on one machine. In Docker, nothing runs on one machine. Every container is its own isolated world. The AI doesn't adjust for this because it doesn't understand what "deployed" actually means for your setup.

The other AI trap: rebuilding instead of configuring

You tell the AI your container is crashing. It suggests rewriting the Dockerfile. New base image. New build steps. New entrypoint. You rebuild, redeploy — and the exact same error comes back, because the problem was never the Dockerfile. The problem was a missing environment variable, or a network setting, or a permissions issue on a mounted volume. None of which live in the Dockerfile.

AI reaches for what it knows: code. But Docker problems are usually configuration problems, and configuration is about your specific environment, your specific infrastructure, your specific deployment. AI can't see any of that.

Still stuck in the restart loop?

MeatButton connects you with a real expert who can read your logs, check your configuration, and find the actual problem instead of guessing. First one's free.

Get MeatButton