Restart Docker Container Automatically After Reboot
In order to operate services using Docker containers reliably, stably and with minimal maintenance effort, it is necessary that they are started automatically after the Docker server is started.
In this tutorial, you will see three different ways to start docker container automatically after reboot.
dockerd
), in other words, you are working with a "normal" Docker installation (not rootless or with Podman).Method 1: The default docker run --restart always Method
If you pass the docker run
with --restart always
option when starting a Docker always, then this container will be started automatically in the future:
docker run -p 8080:80 --name apache -v "${PWD}":/usr/local/apache2/htdocs -d --restart always httpd
There are four possible parameters for --restart
:
--restart no
is the default. If the container terminates, for whatever reason, it will not be restarted.--restart always
causes the container to be restarted automatically as soon as it ends. This restart rule also applies to a reboot of the system. The Docker service is started as part of the init process; this in turn starts all containers that were last--restart always
running with the option. But be careful:--restart always
also applies to a program ending due to an error. If the container contains an error, it can happen that the container is started again and again. The only exception is a manual stopping i. However, if you shut down your system, the container will be started again the next time Docker is restarted.--restart unless-stopped
works very similarly to--restart always
. The difference is that adocker stop
container terminated with will not be started automatically the next time Docker is restarted.--restart on-failure
results in an automatic restart after an error in the container, but no autostart when the Docker system is restarted.
You can determine the restart behavior set for a container with docker inspect
:
docker inspect <containername>
...
"RestartPolicy": {
"Name": "always",
"MaximumRetryCount": 0
},
...
With docker update
you can change the update behavior of a container while it is running:
docker update --restart on-failure <containername>
Read more on restart policy in Docker in the tutorial below.
Method 2: Docker Compose file with the restart option
You can also specify an automatic restart in the file docker-compose.yml
using the keyword restart
:
services:
db:
image: mariadb:latest
restart: always
The four permitted settings are no
(by default), always
, unless-stopped
and on-failure
. The meaning of the keywords is the same as for the previously explained option --restart
of docker run
. The parameterrestart: always
is valid until the docker-compose.yml
services described by the file compose down
are explicitly stopped and deleted by .
Make sure that you restart
specify the keyword at the correct level directly in the settings of the respective container (in the previous example db
).
services:
db:
image: mariadb:latest
volumes:
- vol-db:/var/lib/mysql
environment:
MYSQL_USER: wpuser
MYSQL_PASSWORD: password
restart: always
Method 3: Automatically restart container after reboot with systemd
The manual version of launching Docker containers, and the first one seen in any how-to on the subject, is through the docker run command, which allows you to instantiate a container from a Docker image.
The big drawback of this method is the instability of such a method. Because if the server reboots, or if the internal process stops, or if any other problem occurs, then the docker will stop, and the service provided with it will stop as well.
The logical step is to turn the docker run command into a service so that the system can make sure it runs properly. This is where systemd comes in. It would be perfectly possible to use supervisord
or something like that, but we choosed systemd for this tutorial because it is now massively adopted by default on the most used recent Linux distributions.
Wrapping a Docker container in a systemd service means ensuring that:
- The service will start cleanly when the machine boots
- The container restarts automatically if needed
- Logs (stdout) are managed by Journald and easy to query
- The entire systemd ecosystem can be used and therefore meet concrete needs, such as dependencies, pre/post commands, and centralized environment variable management.
The minimum version of a /etc/systemd/system/nginx.service file would be:
This fully functional file starts a Docker container named nginx, and fetches the latest 'nginx' image from the official docker hub, while passing it a configuration folder as a volume (which Docker will create on the host if it does not exist). The WantedBy
part will only come into play with the command systemctl enable nginx
, in which case the service will be activated at startup because it will be linked to the systemd multi-user target, the default target.
However, this service suffers from several weaknesses. First, if the Docker service is restarted, the service will fail. Also, when the machine boots, the service may try to start before the Docker service is up and running, in which case it could end up failing as well. Consider the BindsTo
and lines After
, which ensure that the service takes Docker as a dependency, and will be shut down first, if Docker is ever stopped.
Then, in the case of Nginx which is a stateless service, it would be ingenious to provide a Docker update when the service starts, in case a more recent version is available. This is feasible by adding a command ExecStartPre
responsible for a docker pull
which will run before the ExecStart
.
Also, you can specify that the service if it falls into error will always be restarted, and this every 10 seconds if necessary, thanks to the lines Restart
and RestartSec
. This is the equivalent of the argument restart=onfailure
to the command docker run
.
Another problem we have with this configuration is that we don't define a behavior for the reload action. In which case, systemd will by default keep the behavior of a restart, by applying stop then start to the service concerned.
The method I use is simply to define and then execute a reload of the nginx process inside the container using ExecReload
. It is also possible to send a signal (kill -s HUP) but I find it cleaner.
Finally, it is possible to vary the names used in the service file using environment variables, line Environment
. If the variables become numerous or if they become common to several service files of the same host, it is possible to use a separate file for its variables, using the option EnvironmentFile
.
An “optimized” service file would therefore look like this:
[Unit]
Description=Docker container
BindsTo=docker.service
After=docker.service
[Service]
Environment=NAME=%N
Environment=IMG=nginx
Restart=on-failure
RestartSec=10
ExecStartPre=-/usr/bin/docker kill ${NAME}
ExecStartPre=-/usr/bin/docker rm ${NAME}
ExecStart=/usr/bin/docker run --name ${NAME} \
-p 80:80 \
-p 443:443 \
-v /srv/nginx/conf.d:/etc/nginx/conf.d \
-v /srv/nginx/html:/usr/share/nginx/html/ \
${IMG}
ExecStop=/usr/bin/docker stop ${NAME}
ExecReload=/usr/bin/docker exec ${NAME} nginx -s reload
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
every time you change the configuration of a .service file.Service logs and logs
One of the big advantages of running all your service files with systemd is that the standard output is fed into the journald mill, which then gives a common and simple way to configure and access an application's logs. To keep the example above, accessing Nginx logs is as simple as:
journalctl -fu nginx
This will not prevent you from having separate log files in the case of virtualhosts, in which case it will be a good idea to share the logs folder (by default /var/log/nginx) of the container with the host machine so as not to lose them on reboot.
Wrapping Up
In this tutorial, you saw three different ways to automatically restart Docker containers after a system reboot.
Though systemd provides a more efficient method with logging, the choice of method largely depends on the environment and specific requirements.
For simpler use cases or single-container setups, the --restart
option in docker run
or Docker Compose might suffice. However, for more complex, multi-service environments, systemd offers greater control, reliability, and integration with system-level processes.