Welcome to the third part of our Docker series. We started with the basics, understanding what Docker is and how to run a simple container with an interactive Bash shell. Then, we escalated things by showing you how to quickly spin up a web server using apache httpd.
If you're new to Docker or missed our earlier posts, I highly recommend checking them out. The foundational knowledge we've built there will certainly help you as we dive into today's topic, Container Lifecycle and Restart Policies.
Docker's ability to manage containers' lifecycles and restart them as needed is one of its most powerful features. It provides reliability, scalability, and helps you maintain your services running smoothly.
So far we've discovered Docker's ability to create isolated environments. But what about the persistence of data? Let's dive into an example that showcases how data is preserved across the life cycle of a Docker container.
Imagine you're working inside an Ubuntu container, and you create a file called
testfile with some content. You then exit the container (stopping the container) but don't delete it. What happens to the file?
1. First, We Create a Container
PS C:\Users\vsurr> docker run --name ubuntu_test -it ubuntu:latest bash Unable to find image 'ubuntu:latest' locally latest: Pulling from library/ubuntu 3153aa388d02: Pull complete Digest: sha256:0bced47fffa3361afa981854fcabcd4577cd43cebbb808cea2b1f33a3dd7f508 Status: Downloaded newer image for ubuntu:latest
This command will create a new Ubuntu container and place us inside a bash shell within the container. If the Ubuntu image is not found locally, Docker will download it.
2. Next, We Make a File Inside the Container
root@5e01e4cd7ac7:/# echo "This is a test file" > testfile root@5e01e4cd7ac7:/# cat testfile This is a test file root@5e01e4cd7ac7:/#
We just created a file named
testfile with the content
This is a test file
3. Exiting Without Killing the Container
In Docker, you can detach from the container and leave it running by using the escape sequence
CTRLkey and press the
- Then immediately press
CTRLkey and press the
After pressing this sequence, you'll be returned to your host command prompt, and the container will continue to run in the background.
4. Stopping the Container
PS C:\Users\vsurr> docker stop ubuntu_test ubuntu_test
We've now stopped our container, everything remains exactly how we left it (hopefully, we will see)
5. Checking Containers
PS C:\Users\vsurr> docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES PS C:\Users\vsurr> docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5e01e4cd7ac7 ubuntu:latest "bash" 2 minutes ago Exited (137) 53 seconds ago ubuntu_test
We can see our stopped container but there are no running containers.
6. Starting the Container Again
PS C:\Users\vsurr> docker start ubuntu_test ubuntu_test
7. Reconnecting to the Container
PS C:\Users\vsurr> docker exec -it ubuntu_test bash root@5e01e4cd7ac7:/#
8. Verifying Our File is Still There
root@5e01e4cd7ac7:/# cat testfile This is a test file
Our file is still there, with the content intact. So what's happening here? The magic lies in how Docker handles the filesystem of a container. When you stop a container, its filesystem remains preserved. Anything you create or modify will still be there when you restart it. It's like stopping and starting a virtual machine.
If you stop and then remove the container using the command
docker rm ubuntu_test, all the data within the container, including our test file, will be gone. This removal deletes the container and all associated files. Once a container is removed, everything inside it is erased, and you start fresh the next time. If you're working with vital data, be mindful of this behaviour, and consider using volumes or other mechanisms for essential persistent storage. We will cover Docker Volumes in the upcoming posts.
Container Restart Policies
Container restart policies determine how Docker should treat containers when they exit. Managing the lifecycle of containers is crucial, and Docker provides several options to control this behaviour.
always- Always restart the container if it stops, regardless of the reason.
unless-stopped- Restart the container unless it has been explicitly stopped by the user.
on-failure- Restart the container if it exits due to an error (a non-zero exit status)
You can set the restart policy directly in the command line when you run a container (or via a Dockerfile), here is the syntax
docker container run --restart=<policy>
norestart policy. This means that if a container exits for any reason, whether due to an error or a normal termination, it will not be automatically restarted by Docker.
This policy always restarts a failed container unless it's been explicitly stopped. This is valuable for critical services that must remain running. When the Docker daemon restarts, the container with this policy will be restarted (even if you have manually stopped the container). For example, if you stop the container with
docker stop and then restart the docker daemon, the container will be restarted.
To demonstrate this, I'm going to spin up a container with the
always policy and attach my terminal to its shell. When I type
exit, the container's main process which is
bash exists so the container also stops. But since we have the
always policy, docker just restarts the container again.
PS C:\Users\vsurr> docker run --name ubuntu_test --restart=always -it ubuntu bash root@0a57bfa8eb7d:/# [I'm inside the container for like 10 seconds] root@0a57bfa8eb7d:/# exit exit PS C:\Users\vsurr> docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0a57bfa8eb7d ubuntu "bash" 17 seconds ago Up 2 seconds ubuntu_test PS C:\Users\vsurr>
This policy will restart the container unless it has been explicitly stopped by the user. This means if you restart the Docker daemon or the host machine, the container will be restarted, but it won't be restarted if you manually stop it.
Let me spin up a new web-server, stop it manually and then restart docker. With the
unless-stopped policy, the web-server will not be restarted.
PS C:\Users\vsurr> docker run -d --name web --restart=unless-stopped -p 8080:80 httpd 5bd33af2ddf204ce04cafe1cd50efbe0c6fcedfbcdde7b692a6a8d77e23ce7dd PS C:\Users\vsurr> docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5bd33af2ddf2 httpd "httpd-foreground" 4 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp web PS C:\Users\vsurr> docker stop web web
PS C:\Users\vsurr> docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5bd33af2ddf2 httpd "httpd-foreground" 4 minutes ago Exited (0) 3 minutes ago web
As you can see the container remains stopped.
on-failure policy, the container will be restarted if it exits with a non-zero exit code, indicating an error or abnormal termination. In computer programming, a non-zero exit code usually signifies that the program has terminated because of an error. Optionally, you can limit the number of times the Docker daemon attempts to restart the container using the
PS C:\Users\vsurr> docker run -d --name failure-demo --restart=on-failure ubuntu bash -c 'sleep 10; exit 1;' e50952d916842463855578f3455c86cb1a7b50ea551d144802dbcd8bb817bc48
The shell command
bash -c 'sleep 10; exit 1;' within the container is designed to cause a failure by exiting with a status of 1 after a 10-second pause. As a result, the container will be restarted by Docker according to the
on-failure policy (every 10 seconds)
PS C:\Users\vsurr> docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e50952d91684 ubuntu "bash -c 'sleep 10; …" About a minute ago Up 9 seconds failure-demo PS C:\Users\vsurr> PS C:\Users\vsurr> docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e50952d91684 ubuntu "bash -c 'sleep 10; …" About a minute ago Up 2 seconds failure-demo
on-failurepolicy, if you manually stop the container and restart docker, the container will be restarted.
By selecting the appropriate policy, you can ensure that your containers behave in alignment with your specific use cases and system requirements.