Cross Compile Containers
Note
This only works because we cross compile outside the
container and copy the results in (notice the FROM scratch
and no RUN
commands). Otherwise we would also need an emulator to run commands within the
container.
Makefile
VERSION = $(shell git describe --long --tags)
BUILD = $(shell date +%FT%T%z)
BUILDSYS = $(shell . /etc/os-release; echo $$PRETTY_NAME)
LDFLAGS = -ldflags "-X 'main.Version=${VERSION}' -X 'main.Build=${BUILD}' -X 'main.BuildSys=${BUILDSYS}'"
REPOTAG = rpicreg.home.arpa:5000/gorepo:$(shell git describe)
.PHONY: gorepo-arm gorepo-amd64 build-arm
# normally we only need the version for the Raspberry Pi. (The programs focus)
all: gorepo-arm gorepo-amd64
gorepo-arm:
GOOS=linux GOARCH=arm GOARM=7 go build -a -tags netgo $(LDFLAGS) -o gorepo-arm .
gorepo-amd64:
GOOS=linux GOARCH=amd64 go build -a -tags netgo $(LDFLAGS) -o gorepo-amd64 .
build-arm: gorepo-arm
echo "Tagging arm/v7 with: $(REPOTAG)"
docker buildx build --platform=linux/arm/v7 --provenance=false --load -t $(REPOTAG) .
Dockerfile
- BUILDPLATFORM
- matches the current machine. (e.g. linux/amd64)
- BUILDOS
- os component of BUILDPLATFORM, e.g. linux
- BUILDARCH
- e.g. amd64, arm64, riscv64
- BUILDVARIANT
- used to set ARM variant, e.g. v7
- TARGETPLATFORM
- The value set with –platform flag on build
- TARGETOS
- OS component from –platform, e.g. linux
- TARGETARCH
- Architecture from –platform, e.g. arm64
- TARGETVARIANT
- used to set ARM variant, e.g. v7
FROM scratch
ARG TARGETARCH
COPY gorepo-$TARGETARCH /bin/gorepo
ENTRYPOINT ["/bin/gorepo"]
CMD ["-addr=:8080"]
EXPOSE 8080
Defining the repositories
For configuring the chromebook docker to allow insecure repos, use file:
/etc/docker/daemon.json
{
"insecure-registries" : [
"rpicreg.home.arpa:5000",
"camus.home.arpa:5000",
"localhost:5000"
]
}
The config for K2s is /etc/rancher/k3s/registries.yaml
mirrors:
rpicreg:5000:
endpoint:
- "http://rpicreg:5000"
rpicreg.home.arpa:5000:
endpoint:
- "http://rpicreg:5000"
s
Create Hugo in Container
One way that I publish my hugo pages is in a docker container or in my
Kubernetes cluster. Both of the places that I run those is on my Raspberry Pi
CM3 system which doesn’t have (until recently) a recent version of hugo. To get
past this I first have docker to build a development container, load Go and
Hugo, and compile the pages. Then I create a second container that doesn’t have
the overhead of an operating system or system libraries, copy in the web pages
and a web server that has been staticly linked
Note
I have Hugo configured to put the result pages in tht doc
directory instead of public
. I could simplify the web server if I put in the
name of the path that I want to server to use (hugo-demo
) in this case.
There are other configuration options (relative pages for example) where I could
make this build and server even more generic. Someday maybe.
Dockerfile
The first container built is temporary. It starts with Alpine Linux 3.20 which
is a small distribution based around Busybox. From the Alpine repository we load
go and hugo.
As of 2024-07-15 we get
- Alpine 3.20.1
- Go 1.22.5
- Hugo 0.125.4+extended
The rest sets the working directory, copies all of the local files (our source
code) into the working directory. Compiles the pages and compiles the web sever.
The second container starts with an empty container and copies the finished web pages and compiled web server from the first container. The it sets up to start the web server by default with no parameters.
# Container 1
FROM alpine:3.20 AS builder
RUN apk add --no-cache hugo go
WORKDIR /hugo-demo
COPY . /hugo-demo/
RUN hugo
RUN go build -a -tags netgo webserver.go
# Container 2
FROM scratch
WORKDIR /hugo-demo
COPY --from=builder /hugo-demo/doc doc
COPY --from=builder /hugo-demo/webserver webserver
EXPOSE 1313
ENTRYPOINT [ "/hugo-demo/webserver" ]
Build using something like:
docker build -t hugo-demo:latest .
Run using something similar to: (or run as daemon for background operation with -d etc.)
docker run --rm -it -p 1313:1313 hugo-demo [optional-parameters-here]
Web Server
This web server serves up pages from the doc
directory. It allows you to put a
prefix on the URL to make it easier to configure in a reverse proxy. Allowable
values really depends on how Hugo was configured. For example, when I wrote this the configuration was:
baseURL = 'http://www.example.com/hugo-demo/'
relativeURLs = false
publishDir = "doc"
Another valid way to configure Hugo is with:
baseURL = '/'
relativeURLs = true
publishDir = "doc"
Now all of the URLs will be relative. Of course that means that site-map and
RSS.xml files will be useless since they don’t have a host to point to. A
discussion on these and other ways to configure Hugo is at
Theme relearn customizations
Note that the redirect on line 20 was for user convenience. If they go to the
root of the website they will be redirected to the top of the documentation.
1package main
2
3// This is a simple web server that serves any file in the current directory
4// (and below).
5import (
6 "flag"
7 "log"
8 "net/http"
9)
10
11var (
12 webAddr = flag.String("web_addr", ":1313", "HTTP service address")
13 prefix = flag.String("prefix", "/hugo-demo/", "Webpage prefix")
14 dir = flag.String("dir", "./doc", "Base of documentation directory.")
15)
16
17func main() {
18 flag.Parse()
19 http.Handle(*prefix, http.StripPrefix(*prefix, http.FileServer(http.Dir(*dir))))
20 http.Handle("/", http.RedirectHandler(*prefix, http.StatusFound))
21 log.Printf("Starting Connection on %s\n", *webAddr)
22 log.Fatal(http.ListenAndServe(*webAddr, nil))
23}