Add Gitea Action to build and push the image for Komodo deploys
Multi-stage Dockerfile builds the web bundle, embeds it into the static Go binary (CGO_ENABLED=0), and ships it in a minimal alpine runtime: non-root user, ca-certificates + tzdata, SQLite on a /data volume, healthcheck on /api/v1/healthz, OCI provenance labels. build-image.yml pushes to the Gitea registry on every branch push: * main -> :latest * any other branch -> :<branch-name> (sanitized to valid tag chars) * every build -> :sha-<short> (immutable, for pinning) A push to a PR branch covers the PR, so there is no separate pull_request trigger. README documents the image, tags, and a docker run / Komodo compose snippet. Modeled on mort's CI. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01JdQpdYYsTgtkJBxbcpAszi
This commit is contained in:
+60
@@ -0,0 +1,60 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
#
|
||||
# pansy ships as one static binary with the web build embedded. This is a
|
||||
# three-stage build: compile the frontend, embed it into the Go binary, then
|
||||
# copy that single binary into a minimal runtime image.
|
||||
|
||||
# ---- stage 1: build the web bundle ------------------------------------------
|
||||
FROM node:22-alpine AS web
|
||||
WORKDIR /web
|
||||
COPY web/package.json web/package-lock.json ./
|
||||
RUN npm ci
|
||||
COPY web/ ./
|
||||
RUN npm run build
|
||||
|
||||
# ---- stage 2: build the static Go binary (web bundle embedded) --------------
|
||||
FROM golang:1.26-alpine AS build
|
||||
ENV CGO_ENABLED=0 GOTOOLCHAIN=auto
|
||||
WORKDIR /src
|
||||
COPY go.mod go.sum ./
|
||||
RUN --mount=type=cache,target=/go/pkg/mod go mod download
|
||||
COPY . .
|
||||
# Overlay the freshly built frontend into the embed directory before compiling
|
||||
# (//go:embed all:dist in internal/webdist).
|
||||
COPY --from=web /web/dist ./internal/webdist/dist
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
go build -trimpath -ldflags "-s -w" -o /out/pansy ./cmd/pansy
|
||||
|
||||
# ---- stage 3: minimal runtime -----------------------------------------------
|
||||
FROM alpine:3.20
|
||||
ARG BUILD_COMMIT=unknown
|
||||
ARG BUILD_BRANCH=unknown
|
||||
ARG BUILD_TIME=unknown
|
||||
LABEL org.opencontainers.image.title="pansy" \
|
||||
org.opencontainers.image.description="Self-hostable garden planner" \
|
||||
org.opencontainers.image.source="https://gitea.stevedudenhoeffer.com/steve/pansy" \
|
||||
org.opencontainers.image.revision="${BUILD_COMMIT}" \
|
||||
org.opencontainers.image.version="${BUILD_BRANCH}" \
|
||||
org.opencontainers.image.created="${BUILD_TIME}"
|
||||
|
||||
# ca-certificates: outbound TLS (OIDC discovery, #5). tzdata: correct local time.
|
||||
RUN apk add --no-cache ca-certificates tzdata \
|
||||
&& adduser -D -u 10001 pansy \
|
||||
&& mkdir -p /data \
|
||||
&& chown pansy:pansy /data
|
||||
|
||||
COPY --from=build /out/pansy /usr/local/bin/pansy
|
||||
|
||||
USER pansy
|
||||
# The SQLite database lives on the /data volume so it survives container updates.
|
||||
ENV PANSY_PORT=8080 \
|
||||
PANSY_DB=/data/pansy.db
|
||||
WORKDIR /data
|
||||
VOLUME /data
|
||||
EXPOSE 8080
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD wget -q -O - "http://127.0.0.1:${PANSY_PORT}/api/v1/healthz" || exit 1
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/pansy"]
|
||||
Reference in New Issue
Block a user