Perfect Tutorial to Run Hugo with Docker, Nginx and Compose

Posted October 10, 2023
Perfect Tutorial to Run Hugo with Docker, Nginx and Compose

Do you want to build Hugo with Docker? This tutorial uses Docker to package Hugo with Nginx. You’ll also learn to use Docker Compose to run Hugo.

What You Will Learn

Along this comprehensive Docker Guide, you will learn the following:

  • How to package a full Hugo app with Docker.
  • If you have external frameworks such as Node.js, This Guide will show you how to run them alongside Docker and Hugo.
  • Hugo is a static site generator. It fits well with static serves such as Nginx. You will be able to serve the Hugo app with Nginx and Docker.
  • If you love working with Docker Compose instead of Dockerfile, you will create a docker-compose.yml config to let Hugo run with Docker Compose.

Prerequisites to Running Hugo with Docker

This guide assumes:

Why Run Hugo App with Docker

Docker packages your Hugo blog, and you don’t need to configure local environments to have your app running.

On top of that, Docker creates a portable image that you can use to deploy your Hugo app on production.

Let’s dive in and build Hugo with Docker like a PRO.

Running Hugo with Docker and Dockerfile

Dockerfile creates the instructions Docker needs to package any application. In this case, you run Hugo to run on Docker. Therefore, create a Dockerfile on your project directory as follows:

# Use the base image 'ubuntu:bionic'
FROM ubuntu:bionic
# Update the package repository
# Install necessary packages
RUN apt-get update && \
    apt-get install -y \
        ca-certificates \
        wget && \
    update-ca-certificates
# Define the Hugo version
ARG HUGO_VERSION="0.117.0"
# Download and install Hugo
RUN wget --quiet "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_Linux-64bit.tar.gz" && \
    tar xzf hugo_${HUGO_VERSION}_Linux-64bit.tar.gz && \
    rm -r hugo_${HUGO_VERSION}_Linux-64bit.tar.gz && \
    mv hugo /usr/bin && \
    chmod 755 /usr/bin/hugo
## Hugo source code
# Set the working directory to '/src'
WORKDIR /src
# Copy code into the '/src' directory
COPY ./ /src
# Command to run when the container starts
CMD ["hugo", "server", "--bind", "0.0.0.0"]

This Dockerfile is enough to package Hugo. In this case:

  • Docker will use ubuntu:bionic to run Hugo.
  • Since this is an Ubuntu distribution Image, you need to update the package repository and install ca-certificates and wget packages, as Hugo will need them.
  • You need the Hugo version running your application added in HUGO_VERSION.
  • Docker will download Hugo on top of ubuntu:bionic. This means it downloads files zipped as tar.gz. This is where ubuntu:bionic comes into play to extract it and set the appropriate permissions for the Hugo executable.
  • With Hugo ready, you can set your WORKDIR and Copy code files.
  • Finally, just like you would run Hugo on the local machine, add your command as specified in the cmd section.

Build and Run Hugo Docker Container

Ensure you are the root of your project containing the above Dockerfile. On your project directory, run the following command to build your Hugo app:

docker build -t hugo-app .

Perfect Tutorial to Run Hugo with Docker, Nginx and Compose

To access your app, run the following command and create a Docker container to run Hugo

docker run -d -p 1313:1313 hugo-app

Docker will create a container and run your app:

Perfect Tutorial to Run Hugo with Docker, Nginx and Compose

Now you can access your app on http://localhost:1313/. Here is my sample app:

Perfect Tutorial to Run Hugo with Docker, Nginx and Compose

Use Docker to Package Hugo and Node.js

Hugo has support for Node.js. This means you installed packages that use Node.js and used them on your Hugo app. Therefore. These packages must be accessible to Docker to make your app function as expected:

Below is your ideal Dockerfile to run Node.js and Hugo with Docker:

FROM ubuntu:bionic

RUN apt-get update && \
    apt-get install -y \
        ca-certificates \
        #Node.js and NPM
        nodejs \
        npm \
        wget && \
    update-ca-certificates

ARG HUGO_VERSION="0.117.0"
RUN wget --quiet "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_Linux-64bit.tar.gz" && \
    tar xzf hugo_${HUGO_VERSION}_Linux-64bit.tar.gz && \
    rm -r hugo_${HUGO_VERSION}_Linux-64bit.tar.gz && \
    mv hugo /usr/bin && \
    chmod 755 /usr/bin/hugo

WORKDIR /src
COPY ./ /src
# Add package files
COPY package.json package-lock.json /src/
# install Node.js packages
RUN npm install
# Run Hugo site
CMD ["hugo", "server", "--bind", "0.0.0.0"]

This looks like your previous Dockerfile. However, you have added the following:

  • Installed Node.js and NPM.
  • Added package.json and package-lock.json files to your Working directory.
  • Used command RUN npm install node.js packages on your Docker Hugo image.

You can now run the following command to build your Hugo app:

docker build -t hugo-app .

To access your app, run the following command and create a Docker container to run Hugo

docker run -d -p 1313:1313 hugo-app

You should be able to access your app on http://localhost:1313/.

Running Hugo with Nginx on Docker

If you are looking to use Nginx to serve your stack blog, then here is your sample Dockerfile:

# Use the Nginx Alpine image as a build stage (temporary image)
FROM nginx:alpine as build
# Install wget in the Alpine-based image
RUN apk add --update \
    wget

# Define the Hugo version
ARG HUGO_VERSION="0.117.0"

# Download and install Hugo
RUN wget --quiet "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_Linux-64bit.tar.gz" && \
    tar xzf hugo_${HUGO_VERSION}_Linux-64bit.tar.gz && \
    rm -r hugo_${HUGO_VERSION}_Linux-64bit.tar.gz && \
    mv hugo /usr/bin && \
    chmod 755 /usr/bin/hugo

# Set the working directory
WORKDIR /src
# Copy code
COPY ./ /src

# Build the Hugo site
RUN hugo --environment production

# Create a new stage with the Nginx Alpine image
FROM nginx:alpine

# Copy the static website files generated by Hugo from the build stage to the Nginx container
COPY --from=build /src/public /usr/share/nginx/html

In this example:

  • You have the first stage, Nginx, to build your image.
  • Nginx uses Alpine, which a Linux distribution. It lets you run commands just like you did use ubuntu:bionic.
  • Since you are using an external server, ensure Hugo first builds your site using the RUN hugo command.
  • All the files RUN hugo generated are static. So, copy them to Nginx.

To test your Hugo Nginx Docker integration, run the following:

docker build -t hugo-app .

To create a container to ace your app, run the following:

docker run -d -p 1313:80 hugo-app

Perfect Tutorial to Run Hugo with Docker, Nginx and Compose

Note: Unlike the previous example, the above command uses port 80. Nginx is served on port 80. So, your command must bind to the same port.

You will now access your app on http://localhost:1313/

If your image is large, I created this Docker Slim With Minimal Reduce Docker Image Size Strategies for you. Check it out.

Conclusion

Along this comprehensive Docker Guide, you have learned the following:

  • How to package a full Hugo app with Docker.
  • How to run Node.js alongside Docker and Hugo.
  • Used Nginx to server Hugo as static.
Perfect Tutorial to Run Hugo with Docker, Nginx and Compose

Written By:

Joseph Chege