Introduction
As others may know, I am a big fan of debian. I like it because of it’s consistency and when I want to reproduce a project, it is very easy to lift my work from one machine to another. Well. Except when that software is built from source or downloaded from their Github because the package repository either doesn’t have it, or if it does, it doesn’t have the latest version. Hugo has been one of those problems.
I have everything I did from my previous post in a git repo so that everything can be tracked, but of course, that git repo doesn’t have the tools I use to compile any of the markdown. Why would it? Very seldom do we package the tools we need in order to run the software we are using. For a project like this, and a powerful tool like Docker and Podman, that paradigm can be different. All we need is a Dockerfile. Almost like having a make
setup, but inside of your repo for your blog posts. I can build this container with the tools I need on the fly, and even upload them to a container registry if I’d like. Now, when I write an article on my laptop compared to my VM, I don’t have to worry about versioning. I build or pull the container, run the commands, and I have the same result on different machines.
Dockerfile
I personally am a fan of Chainguard’s Wolfi image. It feels like Alpine, while making a real effort to smash CVEs as they come about (really useful for businesses), and the shy away from the MUSL Library that I have been burned with in the past and can’t bring myself to use willingly. Maybe I’m missing something I will find in the future, but as of today, thats the base of my images.
I guess a bummer would be that we only have the latest available to us, but that feels like a small price to pay, and honestly a cronjob handles just nicely if you ever need other versions. I have not run into that yet.
./Dockerfile
FROM cgr.dev/chainguard/wolfi-base:latest
Great start. Next I like to define a base application version that I am expecting, then follow the setup guide to install it.
ARG hugoVersion=0.148.1
WORKDIR /app
RUN apk update && \
apk add git bash wget && \
wget https://github.com/gohugoio/hugo/releases/download/v${hugoVersion}/hugo_extended_${hugoVersion}_linux-amd64.tar.gz && \
tar xzf hugo_extended_${hugoVersion}_linux-amd64.tar.gz && \
chmod 777 /app/hugo && \
mv /app/hugo /usr/bin/hugo && \
rm -rf /app/*
USER nonroot
WORKDIR /home/nonroot
The nonroot, I believe, is a wolfi thing. It uses the 65532
ID, which as we will find out soon, causes issues with the internal idea I have with this project. Moving on, building this container should give us a hugo installation that we expect to work. I used an old version of Hugo to test my argument function and because it matched what I was currently running.
podman build \
--no-cache \
--build-arg hugoVersion=0.146.6 \
-t git.ehio.us/sro/astrocoyote:latest \
.
Great! The image builds, let’s see if we can step inside and get the famous version number.
podman run -it --rm git.ehio.us/sro/astrocoyote:latest /bin/bash
hugo version
And failure. Turns out we need to install libstdc++
, which I did not find anywhere in the Go or Hugo Documentation. Oh well. Added that to line 8, and re-running the above commands. I have a working installation. But now, how do have the container act on my data? Easy! Mount the current folder as volume. I use a ./
here for privacy, but naming the full path is best practice. You cannot always depend on where the pod is going to restart.
podman run -it --rm -v "./:/home/nonroot/astrocoyote/" git.ehio.us/sro/astrocoyote:latest /bin/bash
cd astrocoyote
hugo build
# Permission Denied :(
Well of course we get a permission denied. the user that owns these files, id 1000, shares them to this container which is trying to act on them with id 65532. Luckily thanks to these amazing folks
- https://stackoverflow.com/questions/70770437/mapping-of-user-ids
- https://docs.podman.io/en/v4.6.1/markdown/options/userns.container.html#userns-mode
- https://stackoverflow.com/questions/75817076/no-matter-what-i-do-podman-is-mounting-volumes-as-root
We are able to determine that adding --userns=keep-id:uid=65532
made it so my linux system believed that 1000 owned the files, but 65532 was able to control them when the files were mounted. So finally,
podman run -it --rm --userns=keep-id:uid=65532 -v "./:/home/nonroot/astrocoyote/" git.ehio.us/sro/astrocoyote:$version /bin/bash
cd astrocoyote
hugo build
And my project builds!