check / check (push) Successful in 3m45s
.dockerignore now lets .git into the build context, without .git/config, which can hold a remote URL with a credential. ARG VERSION has no default: given none, the build stage takes the version from git describe --tags --always, and fails if the context carries .git and no version comes out. pixad now logs its name, version and architecture as its first log line, through the existing Logger.Identify, which nothing called. Model: opus-5-5
105 lines
3.6 KiB
Docker
105 lines
3.6 KiB
Docker
# Lint stage
|
|
# Same image as Dockerfile.lint: change both pins together.
|
|
# golangci/golangci-lint:v2.12.2-alpine, 2026-08-07
|
|
FROM golangci/golangci-lint:v2.12.2-alpine@sha256:91b27804074a0bacea298707f016911e60cf0cdbc6c7bf5ccacb5f0606d18d60 AS lint
|
|
|
|
WORKDIR /src
|
|
|
|
# script/bootstrap installs the build dependencies and downloads the Go
|
|
# modules. Only script/, go.mod and go.sum are copied first, so this
|
|
# layer is reused until one of them changes.
|
|
COPY script/ ./script/
|
|
COPY go.mod go.sum ./
|
|
RUN script/bootstrap
|
|
|
|
# Copy source code
|
|
COPY . .
|
|
|
|
# Tells script/lint it is inside a container, so it runs the linter.
|
|
ENV container=docker
|
|
|
|
# Run formatting check and linter
|
|
RUN make fmt-check
|
|
RUN make lint
|
|
|
|
# Build stage
|
|
# golang:1.25.4-alpine, 2026-02-25
|
|
FROM golang:1.25.4-alpine@sha256:d3f0cf7723f3429e3f9ed846243970b20a2de7bae6a5b66fc5914e228d831bbb AS builder
|
|
|
|
# Depend on lint stage passing
|
|
COPY --from=lint /src/go.sum /dev/null
|
|
|
|
WORKDIR /src
|
|
|
|
# Build dependencies and Go modules, as in the lint stage
|
|
COPY script/ ./script/
|
|
COPY go.mod go.sum ./
|
|
RUN script/bootstrap
|
|
|
|
# Copy source code
|
|
COPY . .
|
|
|
|
# Run tests
|
|
RUN make test
|
|
|
|
# VERSION is declared here, not earlier: a new value reruns only the
|
|
# build, not script/bootstrap or the tests. Given none, the version is
|
|
# `git describe --tags --always` of the .git in the build context (git
|
|
# comes from script/bootstrap): the tag on a tagged commit, tag-N-gHASH
|
|
# after one, the short commit when no tag is reachable. A context that
|
|
# carries .git and still yields no version fails the build; one without
|
|
# .git, as from a source tarball, stamps an empty version. CGO stays
|
|
# enabled for govips; -trimpath keeps build paths out of the binary, and
|
|
# -s -w leave out the symbol table and debug information.
|
|
ARG VERSION
|
|
RUN version="${VERSION:-$(git describe --tags --always)}"; \
|
|
if [ -e .git ] && { [ -z "$version" ] || [ "$version" = dev ] || \
|
|
[ "$version" = unknown ]; }; then \
|
|
echo "the build context carries .git but yields no version" >&2; \
|
|
exit 1; \
|
|
fi; \
|
|
CGO_ENABLED=1 GOTOOLCHAIN=auto go build -trimpath \
|
|
-ldflags "-s -w -X main.Version=${version}" \
|
|
-o /pixad ./cmd/pixad
|
|
|
|
# Runtime stage
|
|
# alpine:3.21, 2026-02-25
|
|
FROM alpine:3.21@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709
|
|
|
|
# Install runtime dependencies only
|
|
RUN apk add --no-cache \
|
|
vips \
|
|
libheif \
|
|
ca-certificates \
|
|
tzdata \
|
|
su-exec
|
|
|
|
# Copy binary from builder
|
|
COPY --from=builder /pixad /usr/local/bin/pixad
|
|
COPY deploy/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
|
|
|
# Create non-root user, config directory, and data directory. pixad
|
|
# gets uid and gid 65532, which host login and system accounts do not
|
|
# use: a bind-mounted /var/lib/pixa is given to pixad, and on the host
|
|
# it must not belong to a person's account.
|
|
RUN addgroup -g 65532 pixad && \
|
|
adduser -D -H -s /sbin/nologin -u 65532 -G pixad pixad && \
|
|
mkdir -p /var/lib/pixa /etc/pixa && \
|
|
chown pixad:pixad /var/lib/pixa
|
|
|
|
# No USER: the entrypoint must start as root to give a bind-mounted
|
|
# /var/lib/pixa to pixad; it then runs the server as pixad.
|
|
WORKDIR /var/lib/pixa
|
|
|
|
EXPOSE 8080
|
|
|
|
# Shell form so the probe follows PORT; a port set only in a mounted
|
|
# config file is not seen here.
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
CMD wget --spider -q "http://localhost:${PORT:-8080}/.well-known/healthcheck.json" || exit 1
|
|
|
|
# Settings come from PORT and the PIXA_ environment variables; only
|
|
# PIXA_SIGNING_KEY is required. A config file mounted at
|
|
# /etc/pixa/config.yml is optional and is read when present.
|
|
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
|