Batch 1 of the chart-vs-project split. The project now ships a
hardened runtime image as part of every zddc-server release; downstream
deployments (e.g. the Burns & McDonnell Helm chart) will FROM this
image instead of cloning and building from source.
zddc/Containerfile (target: server)
- Tag the runtime stage `server` so `podman build --target server`
is unambiguous (the existing `binaries` target still works).
- Bake the bundled landing + archive tool HTML at /opt/zddc-server/web.
Useful for self-contained demos (`ZDDC_ROOT=/opt/zddc-server/web`)
and as a fallback web root when no external mount is supplied.
- Set fixed UID/GID 1000 for the non-root zddc user so volume
permissions are predictable across hosts.
- Add ENV ZDDC_ROOT=/srv default so a `podman run -v data:/srv` works
with no further config; explicit ZDDC_ROOT overrides.
- Declare VOLUME /srv to make the data-mount expectation explicit.
- Add OCI image labels (title, description, source, documentation,
license, vendor).
- Install ca-certificates so any future outbound HTTPS works.
- Add a HEALTHCHECK for `docker run` users (Kubernetes overrides).
build.sh
- Make the cross-platform podman binary build conditional on `podman`
being present. CI doesn't need it (the runtime container image's
own builder stage produces linux/amd64 internally), but having
build.sh sh-only-runnable means CI doesn't have to do nested
containers just to assemble dist/web.
- Reorder so `zddc/dist/web/` is assembled before the binary build
(allows the binary build to be skipped without breaking the bundle).
.woodpecker.yml (new)
- Triggers on tag push matching `zddc-server-v*`.
- Step 1 (alpine + sh): runs `sh build.sh` to assemble dist/web,
computes the image tag (`${TAG#zddc-server-v}` plus `latest`).
- Step 2 (docker-buildx plugin): builds and publishes
codeberg.org/varasys/zddc-server:{X.Y.Z, latest}. Auth via the
codeberg_user / codeberg_token Woodpecker secrets — these need
one-time setup in repo Settings; documented in zddc/README.md.
zddc/README.md
- New "Container image" section: pull URL, image properties (alpine,
non-root UID 1000, EXPOSE 8443, VOLUME /srv, baked web bundle),
example `podman run` invocation.
- New "Env-var contract (for chart consumers)" table: the variables
Helm charts and Compose files should set explicitly when running
behind a TLS-terminating reverse proxy with SSO. This is the
documented interface between project and downstream charts.
- "Release Tagging" section now points at .woodpecker.yml and lists
the two Woodpecker secrets that must be configured.
Validated locally:
podman build --target server -t zddc-server-test .
podman run -e ZDDC_ROOT=/opt/zddc-server/web -e ZDDC_TLS_CERT=none \
-e ZDDC_INSECURE_DIRECT=1 -e ZDDC_ADDR=:8080 \
-p 18080:8080 zddc-server-test
curl http://localhost:18080/ → HTTP 200, bundled landing tool.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
101 lines
4.5 KiB
Docker
101 lines
4.5 KiB
Docker
# syntax=docker/dockerfile:1
|
|
#
|
|
# Multi-stage build with three useful targets:
|
|
#
|
|
# --target binaries — scratch image holding cross-compiled binaries.
|
|
# Use `podman build --target binaries -o dist/ .`
|
|
# to extract zddc-server-{linux,darwin,windows}-*
|
|
# to the host. No image published from this stage.
|
|
#
|
|
# --target server — alpine-based runtime. Default target. Published
|
|
# as codeberg.org/varasys/zddc-server:vX.Y.Z.
|
|
#
|
|
# Build context expectations (when targeting `server`):
|
|
# dist/web/index.html and dist/web/archive.html must exist —
|
|
# produced by `sh build.sh` from the repo root. CI assembles these
|
|
# before invoking podman. See .woodpecker.yml.
|
|
#
|
|
|
|
# ─── Stage 1: build ──────────────────────────────────────────────────────────
|
|
FROM docker.io/library/golang:1.24-alpine AS builder
|
|
|
|
WORKDIR /src
|
|
|
|
# git is required by go mod for VCS dependencies
|
|
RUN apk add --no-cache git
|
|
|
|
# Skip sum DB checks (allows building with empty/partial go.sum)
|
|
ENV GONOSUMDB=* GOPRIVATE=* GOPROXY=direct
|
|
|
|
# Copy source
|
|
COPY . .
|
|
|
|
# Build linux/amd64 (used by the runtime image and Linux hosts)
|
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" \
|
|
-o /out/zddc-server-linux-amd64 ./cmd/zddc-server
|
|
|
|
# Cross-compile for macOS (Intel and Apple Silicon)
|
|
RUN CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -trimpath -ldflags="-s -w" \
|
|
-o /out/zddc-server-darwin-amd64 ./cmd/zddc-server
|
|
|
|
RUN CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -trimpath -ldflags="-s -w" \
|
|
-o /out/zddc-server-darwin-arm64 ./cmd/zddc-server
|
|
|
|
# Cross-compile for Windows
|
|
RUN CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags="-s -w" \
|
|
-o /out/zddc-server-windows-amd64.exe ./cmd/zddc-server
|
|
|
|
# ─── Stage 2: export binaries ─────────────────────────────────────────────────
|
|
# Use `podman build --target binaries -o dist/ .` to extract binaries to the host.
|
|
# No base image needed — this stage only exists to hold the output files.
|
|
FROM scratch AS binaries
|
|
COPY --from=builder /out/ /
|
|
|
|
# ─── Stage 3: runtime (published image) ─────────────────────────────────────
|
|
FROM docker.io/library/alpine:3.20 AS server
|
|
|
|
LABEL org.opencontainers.image.title="zddc-server" \
|
|
org.opencontainers.image.description="HTTP server for ZDDC archives — ACL via .zddc files, virtual archive index, audit logging" \
|
|
org.opencontainers.image.source="https://codeberg.org/VARASYS/ZDDC" \
|
|
org.opencontainers.image.documentation="https://zddc.varasys.io/zddc-server.html" \
|
|
org.opencontainers.image.licenses="AGPL-3.0-only" \
|
|
org.opencontainers.image.vendor="VARASYS"
|
|
|
|
# wget is in the base image (busybox); explicitly install ca-certificates
|
|
# so outbound HTTPS (e.g. an upstream auth check) works if the operator
|
|
# adds anything later. Keep the install footprint minimal.
|
|
RUN apk add --no-cache ca-certificates && rm -rf /var/cache/apk/*
|
|
|
|
# Non-root user. UID/GID are deliberately fixed so volume permissions are
|
|
# predictable across hosts.
|
|
RUN addgroup -S -g 1000 zddc && adduser -S -u 1000 -G zddc zddc
|
|
|
|
# Binary
|
|
COPY --from=builder /out/zddc-server-linux-amd64 /usr/local/bin/zddc-server
|
|
|
|
# Bundled landing + archive tools — useful for self-contained demos and as
|
|
# a fallback web root. Set ZDDC_ROOT=/opt/zddc-server/web to serve only
|
|
# these (no external data). For real archives, mount the data tree at
|
|
# /srv (the default ZDDC_ROOT below).
|
|
COPY dist/web/index.html /opt/zddc-server/web/index.html
|
|
COPY dist/web/archive.html /opt/zddc-server/web/archive.html
|
|
|
|
# Conventional mount point for the served archive. Operators mount their
|
|
# data here (Azure Files, NFS, hostPath, …). Override with ZDDC_ROOT.
|
|
VOLUME /srv
|
|
|
|
USER zddc
|
|
|
|
# Default config: data mount at /srv. Override at run time as needed.
|
|
# Other env vars (ZDDC_TLS_CERT, ZDDC_EMAIL_HEADER, ZDDC_CORS_ORIGIN, …)
|
|
# are intentionally not defaulted — see zddc/README.md.
|
|
ENV ZDDC_ROOT=/srv
|
|
|
|
EXPOSE 8443
|
|
|
|
# Liveness probe for `docker run` users. Kubernetes deployments override
|
|
# this with their own livenessProbe / readinessProbe.
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
|
|
CMD wget --no-check-certificate -q --spider https://localhost:8443/ || exit 1
|
|
|
|
ENTRYPOINT ["/usr/local/bin/zddc-server"]
|