When you have a good hammer, all problems are nails.

Let’s say you have a Hugo website (this), which was hosted by the generous people at Netlify.

Spoiler: they make money, somehow. And charging of egress traffic is probably the biggest share of income.

Then someone find out that there is no spending limit, and that due to some crappy legal terms (which I am not even sure they are so legal) they can charge you big money in case your website get DDoS.

Others came out with good solutions where to move our tiny websites.

And here is my complex solution: Hugo in a Docker container in a Dokku environment in a small VPS somewhere in Oracle cloud.

Yes, yes… Oracle. Usually the “bad guy”. But so far, it works…


  • A Hugo website as a git repository
  • A Docker host, or a Dokku instance (which automates many steps)

How to

Hugo website are compiled to static HTML, and then they can be served by any web server, without any fancy server-side processing. This boils down to a simple hugo command call. That’s it. Doing this as a Dockerfile step would generate a Docker container with the website static content. Done.

FROM nginx:1.25-alpine
RUN apk add --update hugo git bash sed
WORKDIR /usr/share/nginx/html
RUN rm -rf *
COPY . .
RUN hugo 

We can do better

While the above works, it’s often a good practice to separate the “build” from the “serve” Docker images. This could be done as a 2-steps, where a first container build the website, and the second just serve it.

# Build
FROM alpine:latest AS build
RUN apk add --update hugo git bash sed
WORKDIR /workspace
COPY . .
RUN hugo 

# Serve
FROM nginx:1.25-alpine
WORKDIR /usr/share/nginx/html
COPY --from=build /workspace/public .
# Expose port 80
EXPOSE 80/tcp

And what about redirects? And error pages?

Netlify provides an easy way to declare redirects, that are specified as a _redirects in the root directory. We can ask nginx to do the redirects, and it requires a little regex gymnastic.

Here there is a script that convert a _redirects file into a nginx configuration. If you provide a 404.html and a 50x.html files it would also customize the error pages.

Here the Dockerfile that calls the above and generate the correct nginx configuration during the building phase.

This Dockerfile could easily be changed for other sites generators, just adjust the build command.

On Dokku

For using this with Dokku, just place the files above (Dockerfile, generate_nginx_conf.sh, and _redirects) in the root of your repository. Enable Dockerfile buildpack: dokku builder-dockerfile:set fancywebsite dockerfile-path Dockerfile, and push your repository. This should invoke the server-side build of the container.