Files
Reactorcoremeltdown e999e353f7
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful
Fixed cross-compilation
2026-11-02 16:44:42 +01:00

98 lines
4.0 KiB
Docker

# syntax=docker/dockerfile:1
# KeepOrg synchronization server.
#
# The server is a static binary with no cgo — its only third-party code is
# the two pure-Go database drivers — so the runtime image carries the
# binary, a certificate bundle for talking to an OIDC provider or a
# PostgreSQL server over TLS, and nothing else. There is no shell in it: the binary
# probes its own health.
#
# podman build --format docker -t keeporgd:<version> --build-arg VERSION=<version> .
# docker build -t keeporgd:<version> --build-arg VERSION=<version> .
#
# podman needs --format docker, because the OCI image format has no
# HEALTHCHECK field and drops it silently.
#
# or `make docker`, which takes the version from versions.mk.
FROM golang:1.26-alpine AS build
ARG VERSION=dev
# The platform being built for, so `go build` cross-compiles to it rather than to
# the builder's own architecture.
ARG TARGETOS
ARG TARGETARCH
WORKDIR /src
# Only what the server is built from, so a change to the clients, the
# Android app or the docs does not invalidate this layer.
COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod \
go mod download
COPY cmd/keeporgd ./cmd/keeporgd
COPY internal ./internal
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -trimpath \
-ldflags="-s -w -X main.version=${APP_VERSION}" \
-o /out/keeporgd ./cmd/keeporgd
# Empty directories to copy into the scratch image with the right owner.
# There is no shell there to create them later.
RUN mkdir -p /out/var/lib/keeporg /out/etc/keeporg
FROM scratch
ARG VERSION=dev
LABEL org.opencontainers.image.title="KeepOrg server" \
org.opencontainers.image.description="Synchronization server for collaborative KeePass databases" \
org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.source="https://garage.rcmd.space/keeporg" \
org.opencontainers.image.licenses="AGPL-3.0-or-later" \
cc.tiredsysadmin.application="cc.tiredsysadmin.linux.keeporgd"
# Needed to reach an OIDC provider, or PostgreSQL, over TLS. Nothing else from the builder
# comes along.
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
# The data directory holds the SQLite database, unless KEEPORG_DATABASE_URL
# points at PostgreSQL. Every row in it is sealed under the master key. The
# configuration directory holds server.json and, unless the key is supplied
# otherwise, that master key. They are separate on purpose: whoever holds
# both can read everything, and either alone is useless.
#
# Give the master key somewhere durable, one of these three ways:
#
# --secret keeporg_master_key -e KEEPORG_MASTER_KEY_FILE=/run/secrets/keeporg_master_key
# -e KEEPORG_MASTER_KEY="$(head -c 32 /dev/urandom | base64)"
# -v keeporg-config:/etc/keeporg
#
# The first is preferred: the key is never in the process environment and
# never on a disk this container can write. The file may hold base64 or 32
# raw bytes. Neither environment variable is ever created by the server, so
# a secret that failed to mount is reported instead of being replaced.
#
# With none of the three, the server mints a key into the container's own
# layer on first start and loses it on the next `run`, after which it
# refuses to start: the database does not open with a new key. Nothing is
# overwritten; mount the original key and it starts.
COPY --from=build --chown=65532:65532 /out/var/lib/keeporg /var/lib/keeporg
COPY --from=build --chown=65532:65532 /out/etc/keeporg /etc/keeporg
VOLUME ["/var/lib/keeporg", "/etc/keeporg"]
COPY --from=build /out/keeporgd /keeporgd
# A fixed unprivileged id, matching the convention used by distroless.
USER 65532:65532
EXPOSE 8765
# The image has no shell, so the binary checks itself.
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
CMD ["/keeporgd", "-healthcheck", "-addr", ":8765"]
ENTRYPOINT ["/keeporgd"]
CMD ["-addr", ":8765", "-data", "/var/lib/keeporg"]