Working with Docker and Hugo

Tags: hugo, docker, static-site, repeatable


Using multiple computers with varying operating systems and the associated quirks that come with them can be very annoying quickly. They behave differently depending on which one you’re using and when developing code or using systems a certain way for a while, the behaviour becomes second nature so when you’re switching to a new system or if an update or upgrade changes your workflow it can be a big time cost in getting back up and running.

Thankfully this is a solved problem and there are many ways to skin the cat (terrible expression, sorry!). Docker has become the gold standard and the industry term when one thinks about containers. Sure, there are others but Docker is the one everyone else uses and because of that the community is large, support and forums exist etc. the path is well trodden.

In this post, I’ll quickly discuss how to setup Hugo in a container so that you can take it with you between operating systems, updates and upgrades and it will still continue to work. Why? Because when software is being written you want the ability to create repeatable, testable environments which anyone can use. No longer shall the old “works on my computer” quote be muttered.

In short, you’ll need a computer which can support virtualisation. Most modern computers with moderate processing power support virtualisation. The other requirement is a supported operating system which you can find on the Docker download page.

Once installed I created two files in the root directory of the repository. The first is the docker-compose.yml file which is a set of instructions you can use to build out your container. Read more here: https://docs.docker.com/compose/overview/

services:
  hugoserver:
    build:
      context: .
    volumes:
      - .:/app
    ports:
      - 1313:1313

This file essentially says, that when I run docker-compose up hugoserver to build the dockerfile which is located in the context directory of . (the dot in this case is the current directory), mount . into the folder /app in the container, and then forward port 1313 to port 1313 in the container.

Next I created a Dockerfile file in the same level of the directory as the docker-compose file.

FROM debian:latest

ENV HUGO_VERSION 0.45.1
ENV HUGO_BINARY hugo_${HUGO_VERSION}_Linux-64bit.deb
ENV HUGO_SHA256 e7c8e0b59b11eb3505635eb04a87fdae6c6079f29f85c7b8c68c950a20ecf6c9

# Download
ADD https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/${HUGO_BINARY} /tmp/hugo.deb
# Make sure checksum matches
RUN echo ${HUGO_SHA256}  /tmp/hugo.deb | sha256sum -c -
# Install Hugo & remove install package
RUN dpkg -i /tmp/hugo.deb && rm /tmp/hugo.deb

# Setup container to expose port and where to look for files
EXPOSE 1313
VOLUME /app
WORKDIR /app

# Start the hugo server which is made available to localhost:1313
CMD ["hugo", "server", "--disableFastRender", "--bind=0.0.0.0"]

Hopefully the comments in the file should be clear enough to understand what’s going on at each step, but if not, essentially the Dockerfile starts an instance of the Linux OS Debian. Then it sets up some environment variables which we can use later. Then we download the hugo installer from the source, in this case, Github. Afterwards we match the checksum value to ensure the installer hasn’t been tampered with. Then we install and remove the installer from the tmp directory and expose the container port 1313. We set the app volume as the working directory and run the command: hugo server --disableFastRender --bind=0.0.0.0 This runs the server and allows “anyone” to connect to it. I say anyone because when you’re binding to 0.0.0.0 it means that anyone who can access that container can access it. Usually most operating systems have their firewalls closed by default, unless explicitly opened, others won’t be able to connect.

So if you wanted to take your hugo with you around to different computers and systems you can, much more simply just by using containers.