Creating a Docker Image for a Hugo Website

Combination of the docker,traefik and hugo logo

Have you created a Hugo website and want to deploy it using Docker? This guide will show you how:

  • Create the Dockerfile.
  • Build the image and test it locally.
  • Automate the process using GitLab pipelines and Docker Hub (optional).

Prerequisites

Creating the Dockerfile

First, we need a Dockerfile within our project to build an image. The Dockerfile should be placed in the root directory of our project.

Template

I’m using this Dockerfile for a Hugo application based on the doks theme.

# We use an image where Hugo is already present
FROM hugomods/hugo:exts-0.118.2

# Create a folder for our project
WORKDIR /app

# Copy files into the WORKDIR
COPY . .

# Create an ARG argument for the BASE_URL of the
# Hugo application with a default value
ARG BASE_URL=http://localhost/

# Use BASE_URL if provided as an ENV parameter
ENV BASE_URL=$BASE_URL

# We don't need postinstall scripts because we're using Docker.
# Npm install is necessary if you use a hyas theme like doks.
# If you don't use a hyas theme, npm install doesn't need to be executed.
RUN npm install --ignore-scripts

RUN hugo --baseURL=$BASE_URL

FROM nginx:alpine

# Copy the generated content of the Hugo website
# into the Nginx root directory
COPY --from=0 /app/public /usr/share/nginx/html

# Start Nginx when the container starts
CMD ["nginx", "-g", "daemon off;"]

Building and Testing the Image

The following command builds the Docker image based on the Dockerfile.

docker build -t <INSERT-IMAGE-NAME> .

The next command starts a container using the previously created image as a base on your localhost.

 docker run -d -p 80:80 <INSERT-IMAGE-NAME>

Visit http://localhost in your browser, and you will see your Hugo application. You have successfully deployed your application in a container 🚀.

Process Automation

To automate the process of image creation and uploading to Docker Hub without having to do it manually each time, we will automate it below. Here, we leverage GitLab pipelines. To use them, the following conditions must be met:

  • Project versioning is done through GitLab.
  • There is a .gitlab-ci.yml file in the root directory with the content listed below.
stages:
  - publish_image

variables:
  DOCKER_HUB_USER: "YOUR_DOCKER_USERNAME"
  DOCKER_HUB_REPO: "DOCKER_REPO_NAME"

services:
  # We use a "dind" image (docker in docker),
  # to be able to create the image in the pipeline
  - docker:dind

publish_image:
  image: docker:stable
  stage: publish_image
  script:
    # Build the image
    - docker build -t $DOCKER_HUB_USER/$DOCKER_HUB_REPO .
    # Docker hub auth
    - docker login -u $DOCKER_HUB_USER -p $DOCKER_ACCESS_TOKEN
    # Upload the images
    - docker push $DOCKER_HUB_USER/$DOCKER_HUB_REPO

The variable $DOCKER_ACCESS_TOKEN is a token generated by Docker Hub, allowing GitLab to authenticate with Docker Hub (Token Creation). To restrict access to this token, we store it in GitLab as a variable.

To do this, go to the settings of your repository, then navigate to CI/CD, and click on the ‘Expand’ button. Next, click on ‘Add variable’ and assign DOCKER_ACCESS_TOKEN as the key and the token as the value. This way, the token can be accessed in .gitlab-ci.yaml through the variable $DOCKER_ACCESS_TOKEN.

Alternatively, you can add the variable to a group in which our repository is located