Repository navigation
Expand file tree
/
Copy pathDockerfile
More file actions
131 lines (113 loc) · 5.14 KB
/
Copy pathDockerfile
File metadata and controls
131 lines (113 loc) · 5.14 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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# syntax=docker/dockerfile:1.7
#
# Multi-stage build for bpfcompat. The final image carries the Go binary
# only — qemu/kvm/libbpf are dependencies of the validate flow that runs
# the C validator inside guest VMs, so they belong on the host that
# instantiates this container with /dev/kvm passed through, not in the
# image itself. If you want to embed the C validator and run host-side
# validation from the container, see the "with-validator" target.
#
# Build:
# docker build -t bpfcompat:dev .
# docker build --target with-validator -t bpfcompat:dev-validator .
#
# Run:
# docker run --rm bpfcompat:dev version
#
# Security notes:
# - Final stage is distroless/static so there's no shell, no package
# manager, and no resolver to attack. CVE surface drops to "Go runtime
# and our own code".
# - We run as the unprivileged 'nonroot' uid (65532) baked into the
# distroless image. The API server doesn't need root.
# - Build is reproducible: -trimpath strips host paths and -buildid=""
# drops the build-id, so two builds of the same commit hash produce
# byte-identical binaries.
ARG GO_VERSION=1.26.9
#######################################
# 1. Builder
#######################################
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bookworm@sha256:d9c68c2c51161e12fd77e4c6320687c9cd86e1af1e3ad6e6cd63ff970641453c AS builder
WORKDIR /src
# Copy module manifests first so layer caching skips the download when only
# source files change. vendor/ is mounted via COPY in the bulk step below;
# we don't run `go mod download` separately because we always use the
# vendored set inside the container.
COPY go.mod go.sum ./
COPY vendor/ ./vendor/
# Copy the rest of the source. .dockerignore filters out caches, evidence,
# and on-host artifacts so a bloated workspace doesn't poison the image.
COPY . .
ARG TARGETOS
ARG TARGETARCH
ARG VERSION=dev
ARG COMMIT=unknown
ARG BUILD_DATE=unknown
ENV CGO_ENABLED=0 \
GOOS=${TARGETOS} \
GOARCH=${TARGETARCH}
RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
go build -mod=vendor -trimpath \
-ldflags "-s -w -buildid= \
-X github.com/kernel-guard/bpfcompat/internal/version.Version=${VERSION} \
-X github.com/kernel-guard/bpfcompat/internal/version.Commit=${COMMIT} \
-X github.com/kernel-guard/bpfcompat/internal/version.BuildDate=${BUILD_DATE}" \
-o /out/bpfcompat ./cmd/bpfcompat
# License, notice and patent texts of every Go module linked into the binary
# just built (from its own build information), the Go toolchain's LICENSE and
# PATENTS, and bpfcompat's LICENSE and NOTICE, copied verbatim. Fails the build
# if a linked module has no license file.
RUN bash scripts/collect-go-licenses.sh /out/licenses /out/bpfcompat
#######################################
# 2. Optional stage with the C validator bundled
#######################################
# This is NOT the default target: building the validator pulls in
# libbpf/clang/llvm and bloats the image. It is placed before `final` so
# that a plain `docker build .` (no --target) resolves to the lean `final`
# stage. Build this one explicitly when you need host-side runtime execute
# from inside the container:
# docker build --target with-validator -t bpfcompat:dev-validator .
FROM debian:bookworm-slim@sha256:96e378d7e6531ac9a15ad505478fcc2e69f371b10f5cdf87857c4b8188404716 AS validator-builder
RUN apt-get update -y && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
build-essential \
clang \
llvm \
libbpf-dev \
libelf-dev \
zlib1g-dev \
libzstd-dev \
pkg-config \
make && \
rm -rf /var/lib/apt/lists/*
WORKDIR /src
COPY validator/c-libbpf ./validator/c-libbpf
COPY Makefile ./Makefile
RUN make -C validator/c-libbpf clean all LIBBPF_LINK_MODE=static
FROM gcr.io/distroless/cc-debian12:nonroot@sha256:b0ae8e989418b458e0f25489bc3be523718938a2b70864cc0f6a00af1ddbd985 AS with-validator
WORKDIR /data
COPY --from=builder /out/bpfcompat /usr/local/bin/bpfcompat
COPY --from=validator-builder /src/validator/c-libbpf/bin/bpfcompat-validator \
/usr/libexec/bpfcompat/bpfcompat-validator
USER nonroot:nonroot
ENTRYPOINT ["/usr/local/bin/bpfcompat"]
CMD ["--help"]
#######################################
# 3. Final image (default): Go binary only
#######################################
# Last stage in the file, so `docker build .` with no --target builds this
# lean, validator-free image.
FROM gcr.io/distroless/static-debian12:nonroot@sha256:d093aa3e30dbadd3efe1310db061a14da60299baff8450a17fe0ccc514a16639 AS final
# /data is the conventional mount point for the workdir. Override via
# docker run -v /host/path:/data/.bpfcompat ...
# or via --workdir on the CLI.
WORKDIR /data
COPY --from=builder /out/bpfcompat /usr/local/bin/bpfcompat
COPY --from=builder /out/licenses/ /usr/share/doc/bpfcompat/
# distroless images carry an unprivileged 'nonroot' user (uid 65532) already.
USER nonroot:nonroot
# Entry point is the binary; subcommand is passed via CMD so the typical
# operator override is just `docker run bpfcompat:dev <subcommand>`.
ENTRYPOINT ["/usr/local/bin/bpfcompat"]
CMD ["--help"]