Wojtek @suda Siudzinski


Python/Node/Golang/Rust developer, DIY hacker, rookie designer, 3D print junkie. CEO @ Gaia Charge


Running privileged containers as system services in Swarm mode

Update 11 Jun 2019: A patch by Olli Janatuinen that implements this feature has been merged and should be shipped in Docker 19.06 / 19.09. Thanks Olli!

This title might be misleading so let me clarify: when a node is in Swarm mode, services and stacks don't support privileged or cap_add options. It might be a problem if you're running Concourse or any kind of VPN, you might need this (like I did). This still works if the container was started with docker run but then it has to be manually started and supervised.

Thankfully systemd to the rescue! Following CoreOS systemd pattern of running system (not Docker Swarm) services in Docker, we can create following unit file:

[Unit]
# Set it to your description
Description=My Docker Container service
# Make sure Docker and networking are set up before running this
After=network.target docker.socket
Requires=docker.socket

[Service]
# Equivalent of Docker's `restart_policy`
RestartSec=10
Restart=always
# Give `docker pull` some time
TimeoutStartSec=90
# Use instance name as the container name
Environment="CONTAINER_NAME=%i"
# Set it to your image name
Environment="IMAGE_NAME=alpine:latest"

# Remove any stale containers
ExecStartPre=-/usr/bin/docker rm -f $CONTAINER_NAME
# Pull the image
ExecStartPre=-/usr/bin/docker pull $IMAGE_NAME
# Start the container in the foreground
ExecStart=/usr/bin/docker run --rm --name ${CONTAINER_NAME} ${IMAGE_NAME}
# Stop command
ExecStop=/usr/bin/docker stop $CONTAINER_NAME

[Install]
WantedBy=multi-user.target

as my-service@.service (replace my-service with your service name) and save it in /lib/systemd/system on Ubuntu or /var/systemd/system on other systems.

Now you can create an instance of your service. The @ in service name made it an instantiated unit allowing it to have multiple instances from one config file:

$ sudo systemctl enable --now my-service@INSTANCE_NAME.service

Now running docker ps should show a container named INSTANCE_NAME with your service.

To check the status and logs of your service, you can use systemctl status and journalctl:

$ sudo systemctl status my-service@INSTANCE_NAME.service
$ sudo journalctl --unit my-service@INSTANCE_NAME.service -r

Note: I'm using -r flag for journalctl to see the latest line first. You can also use -f to follow the logs.

Great example of a container running as a systemd service is OpenVPN image from Kyle Manna.

comments powered by Disqus