A Docker container keeps restarting because the process inside it is exiting unexpectedly, and Docker’s restart policy is telling it to bring it back up.
Here’s how to nail down the exact cause:
1. Check the Container Logs:
This is your first stop, always. The logs will tell you why the process inside the container is exiting.
- Diagnosis:
docker logs <container_id_or_name> - Fix: Read the output. Look for error messages, stack traces, or any indication of what went wrong. For example, if you see "permission denied," you’ll need to adjust file permissions within your container image or entrypoint script. If it’s a database connection error, verify your database credentials and network accessibility.
- Why it works:
docker logsstreams standard output and standard error from the container’s main process, which is where application-level errors are usually reported.
2. Examine Container Restart Policies:
Sometimes, the container isn’t failing; it’s just configured to restart frequently.
- Diagnosis:
docker inspect <container_id_or_name> | grep RestartPolicy -A 3 - Fix: If
RestartPolicy.Nameis something like"always"or"on-failure", and you’re seeing rapid restarts without obvious errors in the logs, it might be that the container is exiting cleanly but very quickly (e.g., a script that runs and exits immediately). If you want to stop automatic restarts for debugging, change it to"no":
Then, manually start the container and check logs:docker update --restart no <container_id_or_name>docker start <container_id_or_name> docker logs <container_id_or_name> - Why it works: The
restartpolicy dictates Docker’s behavior when a container’s main process exits. Setting it tonoprevents Docker from automatically restarting the container, allowing you to inspect its state and logs without it disappearing.
3. Resource Constraints (OOM Killer):
The container might be getting killed by the operating system’s Out-Of-Memory (OOM) killer because it’s using too much RAM.
- Diagnosis:
Check the Docker daemon logs and the host system’s kernel logs for OOM killer messages.
You might also see messages in# On Linux hosts sudo journalctl -u docker.service | grep -i oom sudo dmesg | grep -i oomdocker logsif the container process itself is reporting an OOM error before being killed. - Fix:
- Increase container memory limit: If you’re running the container with
--memoryor in a Docker Compose file withmem_limit, increase this value. For example, to give it 2GB of RAM:
Or indocker run -d --memory=2g my_imagedocker-compose.yml:services: my_service: image: my_image deploy: resources: limits: memory: 2G - Optimize application memory usage: If possible, reduce the memory footprint of the application running inside the container.
- Increase container memory limit: If you’re running the container with
- Why it works: The OOM killer terminates processes that exceed available memory to prevent system instability. By providing more memory or reducing usage, you prevent the OOM killer from being invoked.
4. Incorrect CMD or ENTRYPOINT in Dockerfile:
A common issue is that the command specified in the CMD or ENTRYPOINT instruction in the Dockerfile exits immediately, causing the container to stop.
- Diagnosis:
Inspect the Dockerfile for the image:
Look at the last few commands, specificallydocker history <image_name_or_id>CMDandENTRYPOINT. - Fix: Ensure your
CMDorENTRYPOINTexecutes a long-running process (like a web server, database, or a script that keeps running in a loop) or a command that keeps the container alive. If you’re using a script, make sure it doesn’t exit. For example, a common mistake is:
This will run "Hello" and then exit. A correctCMD ["echo", "Hello"]CMDfor a web server might be:
If you’re overriding the default command at runtime, ensure your override is correct:CMD ["nginx", "-g", "daemon off;"]docker run -d my_image my_long_running_command - Why it works: Docker containers are designed to run a primary process. If that process finishes, the container stops. A correct
CMDorENTRYPOINTensures a process that keeps the container running is executed.
5. Healthcheck Failures:
If a healthcheck is configured and it fails repeatedly, Docker might stop and restart the container (depending on the restart policy and orchestration tool).
- Diagnosis:
Check the container’s health status:
You can also check the Docker daemon logs for healthcheck-related messages.docker inspect <container_id_or_name> | grep Health - Fix: Examine the healthcheck command defined in your Dockerfile or
docker runcommand. Ensure it’s correctly checking the application’s health and that the application is actually healthy. If the healthcheck command itself is failing, fix that command or the application it’s supposed to check. For example, if your healthcheck iscurl http://localhost:80/healthand the application isn’t listening on port 80 or the/healthendpoint is broken, the healthcheck will fail. - Why it works: Healthchecks provide a mechanism for Docker to determine if a container is still functioning correctly. If it’s not, Docker can take action, such as restarting it. Fixing the healthcheck ensures it accurately reflects the application’s status.
6. Signal Handling Issues:
The process inside the container might not be handling signals (like SIGTERM or SIGKILL) correctly, leading to unexpected exits or zombie processes.
- Diagnosis:
This is harder to diagnose directly from basic logs. You might see the container exiting very abruptly without a clear error message. Running the container in the foreground and attaching to it can help:
You can also inspect the process tree inside a running container if it stays up long enough.docker run -it --rm --entrypoint /bin/bash my_image # Inside the container, manually run your application's start command # and try sending signals to it (e.g., using 'kill -TERM <pid>') - Fix: Ensure your application is written to handle
SIGTERMgracefully. This usually involves cleaning up resources and exiting cleanly. Many libraries and frameworks handle this by default, but custom applications might need explicit handling. For shell scripts, usingtrapcan help:#!/bin/bash trap 'echo "Caught SIGTERM"; exit 0' SIGTERM # Your application logic here while true; do sleep 1 done - Why it works: When Docker (or an orchestrator) wants to stop a container, it sends a
SIGTERMsignal. If the application doesn’t catch and handle this signal, it might be killed abruptly bySIGKILLor exit in an ungraceful manner, which can sometimes trigger restart policies or leave the container in a bad state.
Once you’ve resolved the restarting issue, you’ll likely encounter the next logical step: ensuring your application is properly configured to handle graceful shutdowns when the container is stopped intentionally.