Deploying Hugo site to DigitalOcean Apps
- 2 minutes read - 403 wordsI’ve been running a DigitalOcean Apps static site for Hugo using the Hugo Buildpack.
I’ve migrated a set of Hugo sites to use Hugo Modules which includes the addition of go.mod
(and go.sum
) files to the Hugo project in order to manage e.g. themes.
Unfortunately, the Hugo Buildpack used by DigitalOcean Apps does not support Hugo Modules. DigitalOcean support recommended that I switch to use a build with a Dockerfile. Unfortunately (!) the recommended Hugo container image (klakegg/hugo
) is outdated (0.107.0). The current version is 0.111.3
.
I decided to write a Dockerfile for myself:
Dockerfile
:
ARG ARCH="linux-amd64"
ARG VERS="0.111.3"
FROM docker.io/busybox:1.36.0 AS install
ARG ARCH
ARG VERS
ARG ENDPOINT="https://github.com/gohugoio/hugo/releases/download"
RUN wget ${ENDPOINT}/v${VERS}/hugo_extended_${VERS}_${ARCH}.tar.gz
RUN tar -xvf hugo_extended_${VERS}_${ARCH}.tar.gz
FROM docker.io/golang:1.20.3-bullseye AS build
COPY --from=install /hugo /usr/local/bin
COPY content content
COPY config.toml config.toml
COPY go.mod go.mod
COPY go.sum go.sum
RUN hugo --environment=production
A requirement for DigitalOcean Apps static sites is that, when using a Dockerfile
, when the resulting container is run, the result should be a folder containing the static site content. The container doesn’t result in a running process (through ENTRYPOINT
).
As you can see in the Dockerfile
, the container:
wget
’s a Hugo Extended (!) release defined byARCH
andVERS
and untar
s ithugo
is used to build the content (into/go/public
)
I used DigitalOcean Apps App Spec to define the static site:
spec.yaml
:
static_sites:
- name: foo
dockerfile_path: Dockerfile
output_dir: /go/public
github:
branch: master
deploy_on_push: true
repo: bar
routes:
- path: /
The Dockerfile
is added to the repo root and the App Spec configures Apps platform to use /go/public
as the output_dir
.
If you use deploy_on_push
, you probably won’t build|run the container image locally and you may not run hugo
locally to build the content. To use the container image locally with e.g. Caddy, you can e.g. append lines to the Dockerfile
to run Caddy:
Dockerfile
:
ARG ARCH="linux-amd64"
ARG VERS="0.111.3"
FROM docker.io/busybox:1.36.0 AS install
ARG ARCH
ARG VERS
ARG ENDPOINT="https://github.com/gohugoio/hugo/releases/download"
RUN wget ${ENDPOINT}/v${VERS}/hugo_extended_${VERS}_${ARCH}.tar.gz
RUN tar -xvf hugo_extended_${VERS}_${ARCH}.tar.gz
FROM docker.io/golang:1.20.3-bullseye AS build
COPY --from=install /hugo /usr/local/bin
COPY content content
COPY config.toml config.toml
COPY go.mod go.mod
COPY go.sum go.sum
# Build the site
RUN hugo --environment=production
# Results in /go/public
# Reflect in spec.yaml output_dir
FROM docker.io/caddy:2.6.4
COPY --from=build /go/public /srv
ENTRYPOINT ["caddy","file-server","--listen=:8080"]
Then:
NAME="..."
VERS=$(git rev-parse HEAD)
podman build \
--tag=${NAME}:${VERS} \
--file=./Dockerfile \
${PWD}
podman run \
--interactive --tty --rm \
--publish=8080:8080/tcp \
localhost/${NAME}:${VERS}
And then browse http://localhost:8080
to view the site.