Docker, Traefik Reverse Proxy and Hugo

1. Background, why this setup

Personnal use, mess with technologies I don’t know well.

I use a OVH server. I want to be able to change server without pain, to get a better deal if needed. Last time a changed my server, it took me maybe a day to move all services.

2. The setup, explain in this post

  • 2 Hugo websites, with let’s encrypt. Moved to docker.
  • Gogs, not yet moved to docker.
  • Traefik, reverse proxy, with docker auto-discovery (and much more).
  • More stuff, that I will take care of later.

3 Hugo docker base Image

I’ve seen some images on docker hub, that download hugo binary and mount the website in the same image. Problem with that is it download binary on every site build. Therefor, I’ve split the hugo build and the website build like that :

Dockerfile or docker pull nsirap/hugo

FROM golang:latest
MAINTAINER nicolas.caen@gmail.com

# Install pygments (for syntax highlighting) 
RUN apt-get -qq update \
&& DEBIAN_FRONTEND=noninteractive apt-get -qq install -y --no-install-recommends python-pygments git ca-certificates asciidoc \
&& rm -rf /var/lib/apt/lists/*

# Download and install hugo
ENV HUGO_VERSION 0.52
ENV HUGO_BINARY hugo_extended_${HUGO_VERSION}_Linux-64bit.deb

ADD https://github.com/spf13/hugo/releases/download/v${HUGO_VERSION}/${HUGO_BINARY} /tmp/hugo.deb
RUN dpkg -i /tmp/hugo.deb \
&& rm /tmp/hugo.deb

TODO: I will change my base image for a lighter. I’ll do quick update if so.

4 Website based on Hugo image

Let’s build the image with the following Dockerfile. The site is on ./site directory.

FROM nsirap/hugo
MAINTAINER nicolas.caen@gmail.com

# Create working directory
RUN mkdir /usr/share/blog
WORKDIR /usr/share/blog

# Expose default hugo port
EXPOSE 1313

# Automatically build site
COPY site/ /usr/share/blog
ONBUILD RUN hugo -d /usr/share/blog/site

# By default, serve site
ENV HUGO_BASE_URL https://nsirap.com
CMD hugo server -b ${HUGO_BASE_URL} --bind=0.0.0.0 --appendPort=false

Note the --appendPort=false that allow to have clean URL even build with server.

5 Gogs (gitlab like clone) installed without docker

I will export my setup in a docker gogs soon, but for now, I leave how it was.

  • before: localhost:3000 reached by apache2 configured like a reverse proxy for this host.
  • after: same binary executed that provide the localhost:3000, but reverse proxy with traefik.

The service is launch with the binary, ./gogs web for now.

6 Traefik

Severall approch possible. I choose the docker based solution. With a Docker-compose configuration file.

6.1 Docker-compose.yml

Let’s have the reverse proxy, and one hugo website setup. Same thing for a second Hugo of course.

version: '3'

services:
  reverse-proxy:
    image: traefik # The official Traefik docker image
    command: --api --docker # Enables the web UI and tells Traefik to listen to docker
    network_mode: host
    ports:
      - "80:80"     # The HTTP port
      - "443:443"
      - "8080:8080" # The Web UI (enabled by --api)
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events
      - ./traefik.toml:/etc/traefik/traefik.toml
      - ./acme.json:/acme.json
  nsirap:
    image: nsirap/nsirap
    labels:
      - "traefik.frontend.rule=Host:nsirap.com"
    ports:
      - "1313:1313"

6.2 traefik.toml

  • The file is with the docker-compose (sourced with the volume part).
  • We have both file and docker provider. The api gives the treafik’s dashboard.
  • Let’s Encrypts is the [acme] parts. Nothing to do, it take care of the certificate..
################################################################
# Global configuration
################################################################
debug = true
#logLevel = "ERROR"
logLevel = "DEBUG"
defaultEntryPoints = ["http", "https"]


################################################################
# Entrypoints configuration
################################################################
[entryPoints]
  [entryPoints.http]
  address = ":80"
    [entryPoints.http.redirect]
    entryPoint = "https"
  [entryPoints.https]
  address = ":443"
  [entryPoints.https.tls]


[file]
watch=true
[backends]
  [backends.gogs]
    [backends.gogs.servers.server1]
    url = "http://127.0.0.1:3000"
    weight = 1


[frontends]
  [frontends.gogs]
  backend = "gogs"
    [frontends.gogs.routes.test_1]
    rule = "Host:git.sirap.ovh"

################################################################
# API and dashboard configuration
################################################################

[api]


[docker]
# endpoint = "unix:///var/run/docker.sock"
#domain = "nsirap.com"
#watch = true
exposedByDefault = true


[acme]
email = "nicolas.caen@gmail.com"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
[acme.httpChallenge]
entryPoint = "http"

7 Final Thought

pro/cons,

  • It take time to have it right, but it’s not too difficult.
  • Easy to move from one server to another, install docker, copy and paste some files.
  • Better server deal ? Here I come. No long migration cost. Spare time are a scare resource.
  • It is fun !

Traefik come with a nice dashboard, and cool logo !

comments powered by Disqus