Repository navigation
Expand file tree
/
Copy pathDockerfile
More file actions
91 lines (76 loc) · 4.13 KB
/
Copy pathDockerfile
File metadata and controls
91 lines (76 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# =============================================================================
# Stage 1: Build
# =============================================================================
# TARGETOS/TARGETARCH are set by Docker Buildx for multi-platform builds (e.g. linux/arm64 on Mac M1).
FROM golang:1.27.3-alpine@sha256:d200d2dd76b03a99b52651fd1325aff7dcd35422c35c01bac56571b0507f3deb AS builder
ARG TARGETOS=linux
ARG TARGETARCH
ARG GOOSE_VERSION=v3.28.0
ARG RIVER_VERSION=v0.49.0
ARG OTEL_VERSION=v1.47.0
ARG GRPC_VERSION=v1.84.0
ARG X_CRYPTO_VERSION=v0.57.0
ARG X_NET_VERSION=v0.60.0
ARG X_SYS_VERSION=v0.48.0
ARG X_TEXT_VERSION=v0.42.0
RUN apk add --no-cache git ca-certificates
WORKDIR /build
# Install goose and river CLI for migrations (for target platform).
# Build them through a temporary module so we can force patched transitive
# versions even when the CLI upstream has not released a dependency bump.
RUN mkdir -p /tmp/migration-tools && \
cd /tmp/migration-tools && \
go mod init migration-tools && \
go get \
github.com/pressly/goose/v3/cmd/goose@${GOOSE_VERSION} \
github.com/riverqueue/river/cmd/river@${RIVER_VERSION} \
go.opentelemetry.io/otel@${OTEL_VERSION} \
golang.org/x/crypto@${X_CRYPTO_VERSION} \
golang.org/x/net@${X_NET_VERSION} \
golang.org/x/sys@${X_SYS_VERSION} \
golang.org/x/text@${X_TEXT_VERSION} \
google.golang.org/grpc@${GRPC_VERSION} && \
CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go install github.com/pressly/goose/v3/cmd/goose && \
CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go install github.com/riverqueue/river/cmd/river
# Cache dependencies
COPY go.mod go.sum ./
RUN go mod download
# Build the application and controlled embedding backfill utility.
COPY . .
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o /build/bin/hub-api ./cmd/api && \
CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o /build/bin/hub-worker ./cmd/worker && \
CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o /build/bin/backfill-embeddings ./cmd/backfill-embeddings
# =============================================================================
# Stage 2: Runtime (default: hub-api)
# =============================================================================
FROM alpine:3.24@sha256:be2656061b536c1883c4034790e21d0a09c5aaaf51968b89368a3c0371ea2c9a
# Require the patched zlib even when the base image contains an older package (CVE-2026-85091).
# Require the CA store that drops emSign ECC Root CA - G3 after the October 2026 eMudhra
# intermediate CA compromise. Both packages are pinned: plain `apk add ca-certificates`
# regenerates the bundle file but leaves the base image's older ca-certificates-bundle installed.
# Require OpenSSL 3.5.9 (busybox wget's TLS and apk) over the base image's 3.5.8.
RUN apk add --no-cache ca-certificates tzdata wget 'zlib>=1.3.2-r1' \
'ca-certificates>=20261020-r0' 'ca-certificates-bundle>=20261020-r0' \
'libssl3>=3.5.9-r0' 'libcrypto3>=3.5.9-r0'
# Create non-root user
RUN addgroup -S app && adduser -S app -G app
WORKDIR /app
# Copy binaries and migration tools from builder
COPY --from=builder /build/bin/hub-api /app/hub-api
COPY --from=builder /build/bin/hub-worker /app/hub-worker
COPY --from=builder /build/bin/backfill-embeddings /app/backfill-embeddings
COPY --from=builder /go/bin/goose /usr/local/bin/goose
COPY --from=builder /go/bin/river /usr/local/bin/river
# Copy migration files
COPY --from=builder /build/migrations /app/migrations
COPY --from=builder /build/openapi.yaml /app/openapi.yaml
# Switch to non-root user
USER app
EXPOSE 8080
# Health check only hub-api. hub-worker and backfill-embeddings do not expose HTTP, so commands
# that reuse this image must not inherit a failing API probe.
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD [ "$(readlink /proc/1/exe)" != "/app/hub-api" ] || wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
# Default: run hub-api. Override the entrypoint for another binary, for example
# docker run --entrypoint /app/hub-worker ... or --entrypoint /app/backfill-embeddings ...
ENTRYPOINT ["/app/hub-api"]