
This is not the first time I want to start a Docker container when my computer starts, but I always forget about how to do it, I will take the chance with this article to document two different ways of doing it.
Restart Policies
This is the official technique provided by Docker. You could control whether your containers start automatically when they exit, or when Docker restarts.
To configure the restart policy for a container use the --restart <value>
flag when using the docker run
command. From potential restart values I suggest to use unless-stopped
value, using this value you are saying to Docker: Ey man!, restart always this container unless it is explicitly stopped.
For more information about potential values please refer to the official documentation.
Let’s use as an example a game that I recently set up inside a container on the Raspberry. Agario Clone is an open source clone from the well-known game Agar.io and I would like this container to start every time my Raspberry goes up. To accomplish this just type:
1 | sudo docker run --name my-agario-server -p 3000:3000 --restart unless-stopped kafebob/rpi-agario |
To check status of the restart policy:
1 | sudo docker inspect -f "{{ .HostConfig.RestartPolicy }}" my-agario-server |
To update the restart policy (for instance remove restart):
1 | sudo docker update --restart=no my-agario-server |
You could also have a look about my kafebob/rpi-agario
container in the article Your own Agario server on Raspberry Pi.
Init system
There maybe times when other services depend on your Docker containers, in these cases it’s much better to use the init system from your operating system. Steps below are useful for Linux users using systemd
as their init system. Nowadays systemd is one of the most popular init systems; Debian, Ubuntu, Raspbian, Arch, Red Hat and many other distributions are using it.
I will try not to go into much detail, since there are many articles describing how to use systemd
, I’m just going to document a couple examples about how you can boot a Docker container using systemd
.
For more information about systemd
I suggest you check out these links:
Step 1 - Create file rpi-agario.service
Assuming that we want to start previous Agario container using systemd
and this container already exists in your host and is called my-agario-server
, create a file named rpi-agario.service
and include following code:
1 | [Unit] |
It looks straightforward, isn’t it?. ExecStart
(Line 8) and ExecStop
(Line 9) are the directives in charge to start and stop the container.
Line 7 is commented out, because I don’t want systemd
restart the service in any case but you could pass values like “always”, “on-success”, “on-failure”, “on-abnormal”, “on-abort”, or “on-watchdog” and these will trigger a restart according to the way that the service was stopped.
Step 2 - Make systemd see your service
Copy file from step 1 in /etc/systemd/system/
and give execution rights to the file.
Now you are going to be able of:
- Enable the service on boot
1 | sudo systemctl enable rpi-agario |
- Check current status
1 | sudo systemctl status rpi-agario |
- Disable the service from boot
1 | sudo systemctl disable rpi-agario |
Aha Moment
An important point to notice from previous init file is the -a flag
in ExecStart
directive, it took me a few hours to realize what was the problem before the Aha Moment.
According to Docker help, -a
or --attach
will attach STDOUT/STDERR and forward signals, if you don’t include this flag Docker is going to start the container through ExecStart
and it will send a success signal, then systemd
will interpret this signal as the process has successfully completed and it will proceed to call ExecStop
and maybe your face will be like mine face during some minutes.
So be aware, always remember to attach consoles and forward signals on the ExecStart
directive.
Scripts at start up
As a final note, if you want to execute scripts instead of docker containers it would be useful directives type=oneshot
and remainafterexit=yes
.
These directives will inform to systemd that the script shall be considered active even when all its processes exited. For instance, I have configured a script to mount some encrypted folders and turn on a nextcloud container, this is how it looks the service descriptor.
1 | [Unit] |
I hope these notes are useful to someone in the world!
Resources
- https://www.freedesktop.org/software/systemd/man/systemd.service.html
- http://container-solutions.com/running-docker-containers-with-systemd/
- https://www.dynacont.net/documentation/linux/Useful_SystemD_commands/
- https://goldmann.pl/blog/2014/07/30/running-docker-containers-as-systemd-services/
- https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files
Happy coding!