diff --git a/Justfile b/Justfile index 98c5135..69dfd85 100644 --- a/Justfile +++ b/Justfile @@ -1,3 +1,5 @@ +# Written and tested 2024-10-21 with just 1.34.0 on Fedora 41 + # See: https://github.com/bigskysoftware/htmx/releases # For static latest: https://github.com/bigskysoftware/htmx/releases/latest/download/htmx.min.js htmx-ver := "2.0.3" @@ -21,7 +23,31 @@ get-htmx: [doc("Cleanup source tree")] [confirm("Are you sure? [y/N]:")] -clean: +clean: clean-container rm -rf .go rm -rf build rm -f htmx.min.js + +# Build the container +build-container: get-htmx + podman build -t htmx-demo -f container/Containerfile . + +# Spin up a production container +run-container: + # Build the image if it doesnt exist + podman image exists htmx-demo || just build-container + + # Stop existing if its running + podman container exists htmx-demo-container && podman stop htmx-demo-container || true + + # Run the container + podman run -d --rm --name htmx-demo-container -p 8085:8080 htmx-demo + @echo "Server running on http://localhost:8085" + +# Remove containers, images and dependencies for container build +clean-container: + podman container exists htmx-demo-container && podman stop htmx-demo-container || true + podman image exists htmx-demo && podman rmi htmx-demo || true + podman image exists golang && podman rmi golang || true + podman image exists alpine && podman rmi alpine || true + podman builder prune -f diff --git a/container/Containerfile b/container/Containerfile new file mode 100644 index 0000000..95bb724 --- /dev/null +++ b/container/Containerfile @@ -0,0 +1,61 @@ +# Written and tested using podman version 5.2.5 + +# See 'man 5 containerfile' for more info +# Alternatively, https://docs.docker.com/reference/dockerfile/#overview + +# Builds the server in an isolated stage +FROM docker.io/golang:alpine as go + +# Get some common dependencies +# NOTE: that 'gcompat' might be required in the runner stage image +# as well for glibc compatibility (sqlite3 is a notable example) +RUN apk add gcompat +RUN apk add gcc +RUN apk add musl-dev +RUN apk add sqlite + +# Set working directory +WORKDIR /build + +# go.mod, go.sum e.t.c. are copied first to leverage caching +ADD go.* . + +# Get the dependencies +RUN go mod download + +# Add the source code, where . is relative to the container build +# context (usually defined directly in the build command) +ADD . . + +RUN CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -o ./server ./*.go + +# Strip the binary for a smaller image, optional +RUN strip ./server + +# The final stage for building a minimal image +FROM docker.io/alpine:latest as runner + +# Add a non-root user and group to facilitate dropping +# privileges inside the container +RUN adduser -D nonroot +RUN addgroup nonroot nonroot + +# Set working directory and make user 'nonroot' the owner +WORKDIR /app +RUN chown nonroot:nonroot /app + +# Copy the server binary +COPY --from=go /build/server server + +# Expose port 8080 +# NOTE: Reserved ports (0-1023) require root privileges +EXPOSE 8080 + +# Drop privileges +USER nonroot:nonroot + +ENV CONTAINER true + +# Run the server +CMD ["./server"] +