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 logs streams 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.Name is 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":
    docker update --restart no <container_id_or_name>
    
    Then, manually start the container and check logs:
    docker start <container_id_or_name>
    docker logs <container_id_or_name>
    
  • Why it works: The restart policy dictates Docker’s behavior when a container’s main process exits. Setting it to no prevents 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.
    # On Linux hosts
    sudo journalctl -u docker.service | grep -i oom
    sudo dmesg | grep -i oom
    
    You might also see messages in docker logs if the container process itself is reporting an OOM error before being killed.
  • Fix:
    • Increase container memory limit: If you’re running the container with --memory or in a Docker Compose file with mem_limit, increase this value. For example, to give it 2GB of RAM:
      docker run -d --memory=2g my_image
      
      Or in docker-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.
  • 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:
    docker history <image_name_or_id>
    
    Look at the last few commands, specifically CMD and ENTRYPOINT.
  • Fix: Ensure your CMD or ENTRYPOINT executes 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:
    CMD ["echo", "Hello"]
    
    This will run "Hello" and then exit. A correct CMD for a web server might be:
    CMD ["nginx", "-g", "daemon off;"]
    
    If you’re overriding the default command at runtime, ensure your override is correct:
    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 CMD or ENTRYPOINT ensures 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:
    docker inspect <container_id_or_name> | grep Health
    
    You can also check the Docker daemon logs for healthcheck-related messages.
  • Fix: Examine the healthcheck command defined in your Dockerfile or docker run command. 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 is curl http://localhost:80/health and the application isn’t listening on port 80 or the /health endpoint 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:
    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>')
    
    You can also inspect the process tree inside a running container if it stays up long enough.
  • Fix: Ensure your application is written to handle SIGTERM gracefully. 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, using trap can 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 SIGTERM signal. If the application doesn’t catch and handle this signal, it might be killed abruptly by SIGKILL or 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.

Want structured learning?

Take the full Docker course →