the ramblings of a random norwegian techie

Kanboard with Docker and Watchtower on Ubuntu 18.10

· by Dennis Eriksen

I’ve never liked Docker. In fact, I’ve always kind of hated it. The reason is simple - I’m an operational engineer. I do operations, not development. And when Docker first came out, everyone jumped on the technology and praised it for making development so much easier. And I agree - containers can make development easier. However, at the time people were setting up Docker containers for everything. And standard prosedure was to set up a container, and forget it. That is a really bad practice, operations-wise. In operations we like things that are automatically maintained, and most tutorials I came across only told you how to get the Docker image up and running. It said nothing about how it should be maintained, and how you could automate that task.

This is still kinda true today. But, as I’ve come to learn with time, best practices have developed, and there exists multiple systems that can maintain your Docker containers for you. I recently received a tip to check out Watchtower, and it seems like a simple and nice tool that can pull the latest version of your images, and run them automatically.. I have come across Watchtower before, but as I’ve mostly been igroring everything Docker, I’ve silently ignored this as well.

Below I will explain how to set up Docker and Watchtower, and lastly, how to set up Kanboard with Watchtower so that it is automatically maintained. Why Kanboard? Just because I want to try it out, and it’s a good example of a simple application that can be deployed with Docker.

Installing Docker

Some of this has been stolen from Digital Oceans article on How To Install and Use Docker on Ubuntu 18.04, which I recommend you read. Also, some is from Dockers own official documentation.

In the article, they want you to add Dockers own repositories. However, I like to use Ubuntus own repositories (just for the maintainability), so I will use that.

First off, update your syste.

$ sudo apt update
$ sudo apt dist-upgrade

Then we can install the Docker-package.

$ sudo apt install docker.io

And that’s it. Let’s check the version.

$ docker --version
Docker version 18.06.1-ce, build e68fc7a

Sweet.

Also, we should add our own user to the docker-group, so we can use Docker without sudo. Also, we need to log into the new group.

$ sudo adduser username docker
$ newgrp docker

You should now be able to control Docker with your own user.

Testing Docker

You can test Docker by simply running the following

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

This tries to start the image hello-world. Docker can’t find the image locally (because we haven’t downloaded any images), so it fetches it from Dockerhub, and runs it.

I will probably add another article later with more info on how to actually use Docker, and how to create your own Docker containers. And also how to build them continously.

Installing Watchtower

Watchtower is itself packaged as a Docker container, which makes “installation” rather easy. It is actually apparently as simple as this:

$ docker run -d \
  --name watchtower \
  -v /var/run/docker.sock:/var/run/docker.sock \
  v2tec/watchtower

We can use docker ps to see if it is running

docker ps
CONTAINER ID  IMAGE             COMMAND        CREATED        STATUS        PORTS  NAMES
d7b9cba16215  v2tec/watchtower  "/watchtower"  3 seconds ago  Up 3 seconds         watchtower

Initializing Watchtower, and other containers

This however, is no way to run a Docker container on a permanent basis. If we reboot the host, the Docker container will stop.

Docker has a way around this. You can specify --restart [no|on-failure|unless-stopped|always]. But this means that you get two init-systems you need to be aware of on your host - both systemd and Docker.

Another alternative is to write a systemd-service file for Watchtower, and every other Docker container that you will be running permanently. If you do this, you also have a nice place to put environmental variables and such as well. Personally, I think I prefer this.

Here is a systemd-service for Watchtower:

[Unit]
Description=Watchtower Docker container
Requires=network.target docker.service
After=docker.service

[Service]
# Don't restart - it will conflict with Watchtower.
Restart=never

# Start with removing old images
ExecStartPre=-/usr/bin/docker rm -f watchtower
ExecStart=/usr/bin/docker run --rm \
                              --name watchtower \
                              -v /var/run/docker.sock:/var/run/docker.sock \
                              v2tec/watchtower \
                              --schedule "0 32 4 * * *" \
                              --cleanup

ExecStop=/usr/bin/docker stop -t 2 watchtower

[Install]
WantedBy=default.target

Installing Kanboard

Alright. Now that we have Docker working, and Watchtower set up, we can set up Kanboard.

I plan on using a systemd-service and Watchtower for Kanboard as well, so let’s start with creating some directories. I plan on using /var/local to store files for Docker.

$ sudo mkdir -p /var/local/docker-kanboard/{data,app,ssl}

When that’s done, we can create our database. I use postgres.

sudo -u postgres psql
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.10.1))
Type "help" for help.

postgres=# create database kanboard;
CREATE DATABASE
postgres=# create user kanboard with encrypted password 'LALALA';
CREATE ROLE
postgres=# grant all on database kanboard to kanboard;
GRANT
postgres=# \q

Also, we need to be able to connect to postgres, so you need to make sure that postgres listens to the right address (I just listen to all interfaces, and use a firewall to make sure no-one can connect externally). And our new Kanboard-user needs permissions to connect from the Docker network.

I’ve added this line in /etc/postgresql/10/main/pg_hba.conf:

host    kanboard        kanboard         172.17.0.0/16          scram-sha-256

This means that any host with an adress in 172.17.0.0/16 can connect to the database kanboard with the user kanboard, using scram-sha-256 as the auth-method.

Now I need a systemd-service for kanboard.

Description=Kanboard Docker container
Requires=network.target docker.service watchtower.service
After=watchtower.service

[Service]
# Don't restart - it will conflict with Watchtower.
Restart=no

#env

# Start with removing old images
ExecStartPre=-/usr/bin/docker rm -f kanboard
ExecStart=/usr/bin/docker run --rm \
                              --name kanboard \
                              -e DATABASE_URL="postgres://kanboard:LALALA@server-hostname:5432/kanboard" \
                              -v /var/local/docker-kanboard/data:/var/www/app/data \
                              -v /var/local/docker-kanboard/plugins:/var/www/app/plugins \
                              -v /var/local/docker-kanboard/ssl:/etc/nginx/ssl \
                              -p 8002:80 \
                              kanboard/kanboard

ExecStop=/usr/bin/docker stop -t 2 kanboard

[Install]
WantedBy=default.target

And that’s kinda it. If I run systemctl start kanboard.service now, I will have kanboard available on port 8002. I can now set up nginx as a reverse proxy for this, so kanboard becomes available on kanboard.example.net.

Now all I need is something to continously build any Docker image I create! I will try to write an article about this some time in the future.