Running WriteFreely on Docker with Traefik

I guess that, by now, it's tradition to restart my blog on various platforms. Here's what it took to run this one using writefreely. I work in company that runs apps, so I always experiment with other tools and this time I am running this blog on #Docker using Traefik to route the data around.

Alright, let's get on with it. This blog post will not describe every single detail, but just overall steps it took for you to read what you are reading now.

Containers

WriteFreely doesn't provide ready-made containers one can simply use in own docker-compose.yml so I built one. Luckily they give us functional Dockerfile so I created it:

git clone https://github.com/writeas/writefreely
cd writefreely/
git checkout v0.12.0
docker build -t kotnik/writefreely:0.12.0 .
docker push kotnik/writefreely:0.12.0

Easy. You can use the image yourself if you want to, this is the latest version as of writing this.

Setup

First time you run it, #WriteFreely needs new keys generated and configuration written. Configuration itself is not complex, you can see here mine. But, in order to generate keys and import config into database you need working environment, and that's the only non-standard issue here.

You see, WriteFreely's docker container fails to start since it can't find those keys, and in order to generate it, you need it running. So, pragmatical as always, I created another image just used for initialization. It's not the smartest thing you will see today:

docker build -t kotnik/writefreely-init:0.12.0 -<<EOF
FROM ubuntu
RUN apt-get update && apt-get install -y wget && rm -rf /var/lib/apt/lists/*
RUN mkdir -p /wf  && cd /wf
RUN wget https://github.com/writeas/writefreely/releases/download/v0.12.0/writefreely_0.12.0_linux_amd64.tar.gz
RUN tar xzvf writefreely_0.12.0_linux_amd64.tar.gz && rm writefreely_0.12.0_linux_amd64.tar.gz
CMD ["sleep", "infinity"]
EOF

Of course, you can use that one yourself too.

And then we go on.

First run

Docker compose file is as you'd expect:

version: "3"

services:
  web:
    image: kotnik/writefreely:0.12.0
    volumes:
      - "./config.ini:/go/config.ini"
      - web-keys:/go/keys
    networks:
      - writefreely
      - web
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.wf.rule=Host(`nikola.kotur.org`)"
      - "traefik.http.routers.wf.tls=true"
      - "traefik.http.routers.wf.tls.certresolver=myresolver"    
      - "traefik.http.routers.wf.entrypoints=web, websecure"
      - "traefik.docker.network=web"

  init:
    image: kotnik/writefreely-init:0.12.0
    volumes:
      - "./config.ini:/go/config.ini"
      - web-keys:/go/keys
    networks:
      - writefreely
    depends_on:
      - db

  db:
    image: "mariadb:latest"
    volumes:
      - db-data:/var/lib/mysql
    networks:
      - writefreely
    environment:
      - MYSQL_ROOT_PASSWORD=silly
      - MYSQL_DATABASE=writefreely
      - MYSQL_PASSWORD=somepassword
      - MYSQL_USER=someusername
    restart: unless-stopped

volumes:
  web-keys:
  db-data:

networks:
  writefreely:
  web:
    external: true

I am not going to go deep into #Traefik labels, if you spend enough time to actually run it you will have no issues understanding mine configuration here. But, first run is a bit different. We need to run the init container first:

docker-compose up -d init

Wait a bit for the database to be auto-created, it will take about the time to fetch that coffee. Then, attach to the init:

docker exec -it writefreely_init_1 bash

Run this once inside:

cd /go && mkdir keys
/writefreely/writefreely config start
/writefreely/writefreely keys generate

Congratulations, your instance is configured.

Running

Stop everything:

docker-compose down

Open docker-compose.yml file and remove init container since you will never need it again. Bring your site up:

docker-compose up -d

Open it in browser and start writing!