A couple of weeks ago, a customer asked me how to restart containers automatically after a reboot of the underlying host. In his context, it was not an insignificant question because some containers are concerned by SQL Server databases and he wanted to stay relaxed as long as possible even after a maintenance of the Linux host by sysadmins. The concerned (DEV) environment doesn’t include container orchestration like Swarm or Kubernetes.
The interesting point is there are several ways to perform the job according to the context. Let’s say I was concerned by services outside Docker that are depend of the containerized database environment.
The first method is a purely sysadmin solution that includes systemd which is a Linux process manager that can be used to automatically restart services that fail with restarting policy values as no, on-success, on-failure, on-abnormal, on-watchdog, on-abort, or always. The latter fits well with my customer scenario.
Is there advantage to use this approach? Well, in my customer context some services outside docker are dependent of the SQL container and using systemd is a good way to control dependencies.
Below the service unit file used during my mission and I have to give credit to the SQL Server Customer Advisory team who published an example of this file included in their monitoring solution based on InfluxDB, Grafana and collectd. The template file includes unit specifiers that make it generic. I just had to change the name of the system unit file accordingly to which container I wanted to control.
[Unit] Description=Docker Container %I Requires=docker.service After=docker.service [Service] TimeoutStartSec=0 Restart=always ExecStart=/usr/bin/docker start -a %i ExecStop=/usr/bin/docker stop -t 2 %i [Install] WantedBy=default.target
Let’s say I have one SQL Server container named sql. The next step will consist in copying the service template to /etc/systemd/system and changing the service name accordingly to the SQL container name. Thus, we may now benefit from the systemctl command capabilities
$ sudo cp ./service-template /email@example.com $ systemctl daemon-reload $ sudo systemctl enable docker-container@sql
That’s it. I may get the status of my new service as following
$ sudo systemctl status docker-container@sql
I can also stop and start my SQL docker container like this:
[clustadmin@docker3 ~]$ sudo systemctl stop docker-container@sql [clustadmin@docker3 ~]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9a8cad6f21f5 microsoft/mssql-server-linux:2017-CU7 "/opt/mssql/bin/sqls…" About an hour ago Exited (0) 7 seconds ago sql
[clustadmin@docker3 ~]$ sudo systemctl start docker-container@sql [clustadmin@docker3 ~]$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9a8cad6f21f5 microsoft/mssql-server-linux:2017-CU7 "/opt/mssql/bin/sqls…" About an hour ago Up 5 seconds 0.0.0.0:1433->1433/tcp sql
This method met my customer requirement but I found one drawback in a specific case when I stop my container from systemctl command and then I restart it by using docker start command. Thus the status is not reported correctly (Active = dead) and I have to run systemctl restart command against my container to go back to normal. I will probably update this post or to write another one after getting some information on this topic or just feel free to comments: I’m willing to hear about you!
The second method I also proposed to my customer for other SQL containers without any external dependencies was to rely on the Docker container restart policy capability. This is a powerful feature and very simple to implement with either docker run command or Dockerfile as follows:
docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=P@$$w0rd1' -p 1433:1433 --restart=unless-stopped -d microsoft/mssql-server-linux:2017-CU7
Restart-policy values as Always and unless-stopped fit well with my customer scenario even if I prefer the latter option because it provides another level of control if you manually decide to stop the container for any reasons.
I will voluntary omit the third method that consist in installing systemd directly into the container because it is not recommended by Docker itself and not suitable with my customer case as well.