Run and Develop Hugo in a Docker Container

Published: 2024-06-05 | Updated: 2024-07-02

I like to keep my development machine as pristine as possible, and for keeping my projects under development as separated as possible, Docker is a no-brainer.

With separate Docker containers for each project nothing in project A can ever interfere with something going on in project B. All projects effectively run on serarate machines. Not only that, but as many projects as necessary can be in active development at the same time.

My setup for each project lives in a .docker folder in the project root. It consists of 3 files: .env, compose.yml, and start.sh.

What I love about this setup is all it takes to start up a new project is a quick modification to the .env file and I’m off to the races. Here’s what’s in mine for this site:

# DOCKER ENVIRONMENT FILE
COMPOSE_PROJECT_NAME    = hugo_tdstg
HOST_MACHINE_PORT       = 2020
VIRTUAL_HOST            = tdstg.localhost

My Docker Compose file is pretty simple too:

name: $COMPOSE_PROJECT_NAME

services:
  hugo:
    env_file:
      - .env
    image: hugomods/hugo:exts
    container_name: ${COMPOSE_PROJECT_NAME}
    restart: unless-stopped
    volumes:
      - ../:/src
      - $HOME/hugo_cache:/tmp/hugo_cache
    working_dir: /src
    ports:
      - ${HOST_MACHINE_PORT}:${HOST_MACHINE_PORT}
    stdin_open: true # docker run -i
    tty: true        # docker run -t
    command: /bin/sh -c ".docker/start.sh"

networks:
  default:
    name: local-network
    external: true

There is nothing in this compose file which ever needs to change when starting up a new development container.

And finally, my startup script, which Docker runs automatically

#!/bin/sh

set -e  # quit on any error

echo Starting HUGO Development Server on port $HOST_MACHINE_PORT

# index the site
npx -y pagefind --site public && \
hugo server -p $HOST_MACHINE_PORT --disableFastRender --gc --ignoreCache --bind 0.0.0.0 --appendPort=false

Like compose.yml, start.sh never needs to be modified. They get everything they need from the .env file. So all it takes is to pick a project name and a port on my host machine and I’m good to go. Simple and fast.