Docker Container Keeps Restarting Continuously (CrashLoopBackOff)
Quick answer
A container stuck restarting continuously means the main process inside it crashes immediately every time it starts — the actual fix requires capturing the...
A container stuck restarting continuously means the main process inside it crashes immediately every time it starts — the actual fix requires capturing the crash reason before the automatic restart clears it, since by the time you check the container's status, it's often already restarted into a fresh, uninformative state.
The Problem
A container never reaches a stable running state, cycling through restarts indefinitely:
docker ps
CONTAINER ID STATUS
a1b2c3d4e5f6 Restarting (1) 3 seconds ago
In Kubernetes environments specifically, this same underlying pattern is labeled explicitly as CrashLoopBackOff, with Kubernetes progressively increasing the delay between restart attempts.
Why It Happens
The container's restart policy (always, unless-stopped, or Kubernetes' own restart handling) causes Docker/Kubernetes to keep relaunching the container after every crash, which is the correct, intended behavior for recovering from transient failures — but if the crash is caused by something that will happen identically every single time (a missing environment variable, a bad configuration, a bug triggered immediately on startup), the container simply crashes again immediately after each restart, producing the endless loop. Common specific causes:
- A required environment variable or configuration file is missing, causing the application to fail its own startup validation immediately every time
- The application depends on another service (a database, a cache) that isn't ready yet, and the application doesn't retry gracefully — it crashes outright on the first failed connection attempt instead
- A genuine bug in application startup code that fails unconditionally, regardless of environment or timing
- Insufficient memory causing the process to be killed by the OOM killer immediately after starting, which then triggers an automatic restart into the same insufficient-memory situation again
The Fix
First, capture the actual crash output before it's lost to the next restart cycle. Docker retains logs from the most recent exited attempt, even while the container is actively restarting:
docker logs a1b2c3d4e5f6
If the container restarts too quickly to catch meaningful logs this way, temporarily override the restart policy to prevent immediate re-launching, giving you a stable window to investigate:
docker update --restart=no a1b2c3d4e5f6
docker start a1b2c3d4e5f6
docker logs -f a1b2c3d4e5f6
With the restart policy temporarily disabled, the container stays in its exited state after the crash rather than immediately relaunching, giving you time to read the full crash output at your own pace.
Check the container's exit code for a general category of cause, even before diving into the specific log content:
docker inspect a1b2c3d4e5f6 --format='{{.State.ExitCode}}'
Exit code 1 typically indicates a general application error (check logs for specifics); exit code 137 indicates the process was killed, commonly by the OOM killer for exceeding memory limits; exit code 127 typically means the command specified in CMD/ENTRYPOINT doesn't exist inside the image at all.
If the cause is a missing environment variable or configuration, verify exactly what the container actually received at startup, since a value might be correctly set in your intended configuration but not actually reaching the container due to a separate configuration issue:
docker inspect a1b2c3d4e5f6 --format='{{range .Config.Env}}{{println .}}{{end}}'
If the crash is caused by a dependency (like a database) not being ready yet, add proper retry logic to the application's own startup sequence rather than relying purely on container orchestration timing, since even correctly configured startup ordering (like Compose's depends_on with health checks) doesn't guarantee the dependency is fully ready to accept connections the instant it reports as "started":
# Application-level retry example, pseudocode
for attempt in range(10):
try:
connect_to_database()
break
except ConnectionError:
time.sleep(2 ** attempt) # exponential backoff
Still Not Working?
If the crash reason still isn't clear from logs and exit codes alone, run the container interactively with its entrypoint overridden to a shell, letting you manually execute the actual startup command step by step and observe exactly where and why it fails, rather than relying only on whatever output the application itself chooses to log before crashing:
docker run -it --entrypoint sh your-image
# then manually run the actual startup command from inside the container