Why did my Docker container stop?

When you run a container you’ve pulled from Docker Hub, or another registry, you are launching a process, which will eventually complete. Sooner or later, your Docker container will come to a complete stop, whether by choice or accident.

The fact that a Docker container is exiting doesn’t usually indicate that something is wrong. But, nevertheless, you might be wondering why it’s exited.

Containers are not like virtual machines, which will keep running until you tell them to stop. Containers generally run a specific process, and when this process finishes, the container exits.

So why does a container stop?

The lifecycle of a container

To understand why and when a container stops, we need to look at the lifecycle of a container. A Docker container goes through various stages of life - like a bee 🐝.

Diagram showing the states of a Docker container
Docker container lifecycle

A container is simply an isolated process running on your computer. A Docker container can be in one of several core states:

  • Created - The Docker container has been created, but not started (e.g. after using docker create)

  • Up - The Docker container is currently running. That is, the process inside the container is running. Can happen using docker start or docker run.

  • Paused - The Docker container has been paused, usually with the command docker pause.

  • Exited - The Docker container has exited, usually because the process inside the container has exited.

Why a Docker container terminates

So why does a container terminate, or exit? There are several reasons why a Docker container might end:

  • The main process inside the container has ended successfully: This is the most common reason for a Docker container to stop! When the process running inside your container ends, the container will exit.

    Here are a couple of examples:

    • You run a container, which runs a shell script to perform some tasks. When the shell script completes, the container will exit, because there’s nothing left for the container to run.

    • You run a utility which is packaged as a Docker container, like the Busybox or Maven images. When the utility finishes, the container exits.

  • The process inside the container has been terminated: This is when the program that runs inside the container is given a signal to shut down. This happens if you run a foreground container (using docker run), and then press Ctrl+C when the program is running. When this happens, the program will stop, and the container will exit.

  • The container has been stopped using docker stop: You can manually stop a container using the docker stop command.

  • The Docker daemon has restarted, and it terminated and restarted the container: Docker can restart containers if you need it to. By default, Docker doesn’t automatically restart containers when they exit, or when Docker itself restarts. To configure Docker to restart containers automatically, use a restart policy using the --restart switch, when you run a container using docker run.

  • The container has consumed too much memory, and has been killed by the host OS: If the operating system detects that it’s running out of memory, it might start killing processes to free up memory. If a container is using a lot of memory or resources, it might be killed by the OS. You can set hard memory limits on your container by using the -m switch with docker run.

Game Over on a video game screen
When the process ends, it’s game over for your Docker container

How to find out why a Docker container exits

If you run a container and it’s terminating unexpectedly, and you’re not sure why, you need to think about what the container is doing when it starts. Is the script that is running inside the container exiting? Is the application crashing?

To find out what’s going on, you need to get more information about the container. You can get this information by looking at a container’s logs and its state.

1. Look at the logs

The best way to explore what goes on inside a Docker container is to look at the logs using docker logs <container_id>:

  • Do the logs show the application starting up properly?

  • Can you see any helpful debug messages from the application?

  • Does the application crash with a stack trace (e.g. Java) or some other debugging information?

You’ll need to figure out whether the logs give you a clue as to why the process is exiting unexpectedly.

2. Check the state of the container

You can view details about a container by using docker inspect <container_id>. This command shows a lot of information about the container, including its state. The state includes information like the container’s exit code and perhaps the error message that was returned:

"State": {
    "Status": "exited",
    "Running": false,
    "Paused": false,
    "Restarting": false,
    "OOMKilled": false,
    "Dead": false,
    "Pid": 0,
    "ExitCode": 0,
    "Error": "",
    "StartedAt": "2020-10-30T11:44:56.344308725Z",
    "FinishedAt": "2020-10-30T11:48:23.434250526Z",
    "Healthcheck": {
        "Status": "",
        "FailingStreak": 0,
        "Log": null

Look at the container’s exit code. In this example, the container’s exit code was 0. An exit code or exit status of 0 generally means that the application successfully completed. But any other exit code indicates an unsuccessful exit. Some exit codes have further, specific meanings, which you might need to check with the person who wrote the program.

Help! My Docker container dies immediately

If you run a container and it terminates immediately, it is frustrating to figure out what’s going on. But fear not. You can debug this situation by creating a shell in the container, to give you time to run the offending script, and troubleshoot the issue.

To debug this situation and find out why the container is stopping, create and start a container from the same failing image, and override the entrypoint with a shell, like sh or bash. This will start the container, and drop you in to a shell session, where you can run your script, and see whether it is exiting unexpectedly.

Example: The following command runs the nginx:latest image, but overrides its default entrypoint. The default entrypoint will normally start the nginx web server. But when we run this command, the container starts, and opens a shell, so that you can do some debugging inside the container. Perhaps you would use the shell to run the usual entrypoint startup script, and see what’s happening, or print out some environment variables:

docker run --interactive --tty --entrypoint /bin/sh nginx:latest

How to prevent a container from stopping

So how do you prevent a container from stopping?

Perhaps you have a script which runs in a container, and it’s terminating too early.

Or maybe you want to run a few commands in a container, and keep it running in the background when you’re not using it. (This isn’t the ideal use for containers, but sometimes it’s useful.)

There are a few ways that you can prevent a container from stopping - all of these are simply ways to keep a process alive:

  • Run a long-lived service inside the container: Most containers run a long-living service, like a database or a web server. These processes keep running until they receive a shutdown signal. This is the usual way that a container runs for an extended period without stopping – because the underlying process keeps running.

  • Add an artificial sleep or pause to the entrypoint: If your container is running a short-lived process, the container will stop when it completes. You can artificially extend this by adding some code to the entrypoint script (if you have one), to wait or sleep for a while. You could tell the script to sleep for a fixed period, or perhaps tell it to sleep indefinitely. For example, in bash, you can use this to create an infinite pause: while true; do sleep 1; done.

  • Change the entrypoint to an interactive shell: This is useful if you want to use a container like a virtual machine, and keep it running in the background when you’re not using it. If you override the entrypoint to the container with a shell, like sh or bash, and run the container with the -itd switches, Docker will run the container, detach it (run it in the background), and attach an interactive terminal. Note that this won’t run the container’s default entrypoint script, but run a shell instead. Effectively, you will have a container that stays running permanently. For example: docker run --entrypoint /bin/sh -itd mycontainer:latest

In the real world

When people use containers in the real world, how do they keep them alive?

Docker containers are used, literally, to contain an existing application. They are a way of putting an application in its own box, so it has limited access to resources. Containers are often used for long-running processes, like web servers or database servers, or for short-lived utilities, like fetching a web site or copying a file.

Containers aren’t usually used like general-purpose virtual machines. They are designed to run, or contain, a single application. This allows them to start up fast, and to exit when no longer needed (which usually happens when the main process inside the container has finished).

However you choose to keep your container alive, remember that Docker containers are at their simplest and most powerful when they are used to contain a single process, from startup to completion.