Docker Container Keeps Restarting: Why It Crashes and How to Stop the Loop
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:
- Missing environment variables. Your app expects a database URL, an API key, or a secret token. It's not there. The app dies.
- Can't connect to the database. The app starts, tries to connect to the database as the very first thing it does, and the database isn't reachable. Maybe it's on a different network. Maybe it hasn't started yet. Maybe the connection string is wrong.
- Wrong startup command. The Dockerfile says to run
python app.pybut the file is actually calledmain.py. Or it saysnpm startbut there's no start script defined in package.json.
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:
- 0 — the app exited normally. It thinks it's done. This usually means your startup command finishes immediately instead of staying running.
- 1 — generic error. The app crashed. The logs will tell you why.
- 137 — killed by Docker. Out of memory, or Docker got a stop signal.
- 139 — segfault. The app tried to access memory it shouldn't have. Usually a native dependency problem.
- 126 — the command can't be executed. Wrong permissions on the startup script.
- 127 — command not found. The startup command in your Dockerfile doesn't exist in the container.
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