-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile.iperf
More file actions
117 lines (115 loc) · 7.69 KB
/
Copy pathDockerfile.iperf
File metadata and controls
117 lines (115 loc) · 7.69 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
# iperf3-enabled image variant. Same prebuilt, CAP_NET_RAW-stamped pingularity
# binary as the default Dockerfile, but the final stage is debian:13-slim + iperf3
# so the opt-in iperf3 speedtest engine has a binary to exec. The default image
# is distroless/static-debian13 with NO package manager, so iperf3 can never be
# present there; this variant exists only for users who select the iperf3 engine.
# See Dockerfile for the default (lean, iperf-free) image.
#
# The base must ship iperf3 >= 3.17: IperfVersion in internal/speedtest warns on
# every older build (the 3.17 authentication-padding change), so a base that apt-
# installs less than that makes the image flag its own binary. trixie carries 3.18;
# bookworm's 3.12 is why the base can never fall back a Debian generation.
#
# Multi-arch works exactly like the default image: goreleaser (dockers_v2) stages
# the per-platform binaries - linux/amd64/pingularity, linux/arm64/pingularity -
# in the build context and buildx selects the target-arch one via $TARGETPLATFORM.
# The difference here is the final stage runs apt for the TARGET arch (under QEMU
# when cross-building; the release workflow already sets up buildx + QEMU). setcap
# stays on $BUILDPLATFORM so it still runs natively without emulation.
#
# Both FROM lines are pinned by digest (alongside the tag) so Dependabot's docker
# ecosystem can bump them; the debian:13-slim digest is kept identical to the one
# in the default Dockerfile so the two bases stay in lock-step.
# --- stamp CAP_NET_RAW onto the binary (runs natively on the build host) ---
FROM --platform=$BUILDPLATFORM debian:13-slim@sha256:3a39a0592364683e6bab97937b72cad5a8fa6dcbbee90edb3bb48c7f8e94f258 AS setcap
RUN apt-get update \
&& apt-get install -y --no-install-recommends libcap2-bin \
&& rm -rf /var/lib/apt/lists/*
# TARGETPLATFORM (set by buildx per target arch) selects the matching prebuilt
# binary; this stage stays pinned to $BUILDPLATFORM above so apt + setcap run
# natively without QEMU.
ARG TARGETPLATFORM
COPY $TARGETPLATFORM/pingularity /pingularity
# +ep: effective+permitted, so the cap is raised automatically on exec even for a
# non-root user. `mkdir /data` seeds the data dir the final stage chowns. BuildKit
# preserves the security.capability xattr across the COPY into the final image
# (same guarantee the default Dockerfile relies on), so the final stage needs no
# libcap2-bin of its own.
# The .pingularity-image-dir marker is a volume-lineage HEURISTIC (not a proof
# of volume type): Docker's copy-up carries it into a fresh named volume, so the
# daemon's container carve-out (store.go) can tell content that came from OUR
# image from an empty PVC or a plain bind-mounted host directory, which never
# carry it. A bind mount restored FROM a marked volume would carry it too - an
# accepted edge, since the content is genuinely ours.
RUN setcap cap_net_raw+ep /pingularity && mkdir -p /data && touch /data/.pingularity-image-dir
# --- final image: debian-slim carrying iperf3 + the capped binary ---
FROM debian:13-slim@sha256:3a39a0592364683e6bab97937b72cad5a8fa6dcbbee90edb3bb48c7f8e94f258
# Static attribution; version/revision are stamped per build by goreleaser
# (dockers_v2 labels/annotations in .goreleaser.yaml), not hardcoded here.
LABEL org.opencontainers.image.title="pingularity" \
org.opencontainers.image.description="Single-binary internet-connectivity monitor (iperf3-enabled image variant)." \
org.opencontainers.image.source="https://github.com/pingular/pingularity" \
org.opencontainers.image.licenses="MIT"
# iperf3 gives the opt-in engine a binary to exec (pingularity looks it up on PATH
# via exec.LookPath; the debian package installs /usr/bin/iperf3, pulling libiperf0
# as a dependency). ca-certificates + tzdata are bundled by the distroless/static
# base of the default image, so install them here too: without ca-certificates the
# static Go binary's TLS calls (Ookla, the update feed) fail x509 verification, and
# tzdata keeps time-zone handling identical to the default image.
RUN apt-get update \
&& apt-get install -y --no-install-recommends iperf3 ca-certificates tzdata \
&& rm -rf /var/lib/apt/lists/*
# debian has no distroless `nonroot` account, so recreate the SAME uid/gid (65532)
# the default image runs as. This keeps the volume-ownership contract identical: a
# freshly created named volume inherits 65532 and the unprivileged process can
# write its database + pingularity.key. Creating the account (not just USER 65532)
# also restores the /etc/passwd entry distroless `nonroot` provides, so uid->name
# lookups resolve.
RUN groupadd --gid 65532 pingularity \
&& useradd --uid 65532 --gid 65532 --no-create-home --home-dir /var/lib/pingularity --shell /usr/sbin/nologin pingularity
COPY --from=setcap /pingularity /pingularity
# The licences the binary is distributed under. Every other channel carries these
# - the archives ship them beside the binary (.goreleaser.yaml archives.files) and
# the deb/rpm install them under /usr/share/doc/pingularity - but an image is a
# binary distribution too, and the statically-linked binary carries BSD-3 code
# (golang.org/x, speedtest-go, the modernc/musl-derived libc) plus an embedded
# OFL font, all of which ask for their notice to travel with it. goreleaser stages
# only the built binaries into the docker context, so both files are named in that
# builder's extra_files; without them this COPY fails the build rather than
# silently shipping an image with no notices.
COPY LICENSE THIRD-PARTY-NOTICES.md /usr/share/doc/pingularity/
# The data dir must exist owned by 65532 so a freshly created named volume inherits
# that ownership and the unprivileged process can write to it.
# --chmod=0700 to match the mode pingularity gives a data directory it creates
# itself; see the same COPY in Dockerfile. Without it the destination directory is
# 0755 (COPY does not carry the source mode across) and the daemon spends every
# start warning that its own data directory is readable by others.
COPY --from=setcap --chown=65532:65532 --chmod=0700 /data /var/lib/pingularity
# Belt and braces: some BuildKit versions apply COPY --chmod to the files but
# not the directory itself (observed: buildx honors it, ubuntu-latest's plain
# docker build does not), and this image HAS a shell to correct it. The
# distroless default image cannot RUN anything, so it seeds the directory one
# level down and copies it as an entry instead - see the COPY in Dockerfile.
# The daemon also tightens its own container data dir at boot either way
# (store.go's container carve-out).
RUN chmod 0700 /var/lib/pingularity
EXPOSE 9000
VOLUME /var/lib/pingularity
# Start in the writable data dir rather than / (unwritable for uid 65532), the
# same guarantee the distroless base gives the default image via /home/nonroot:
# anything that resolves a relative path lands somewhere the process can write.
WORKDIR /var/lib/pingularity
USER pingularity
# Same healthcheck as the default image, exec form for parity (this image has a
# shell, but the contract is one probe in both variants). The subcommand probes
# http://127.0.0.1:9000/healthz; operators who change -listen must override this
# healthcheck (or disable it), or the container reports unhealthy while the
# daemon is fine.
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s \
CMD ["/pingularity", "healthz"]
# Pin the database onto the volume, exactly as the default image does: without this
# the path is chosen from the effective uid and a --user override would fall back to
# a temp dir inside the writable layer, leaving the mounted volume empty so updates
# silently discard all history plus pingularity.key. The key lives beside the
# database, so pinning -db pins both.
ENTRYPOINT ["/pingularity", "run", "-db", "/var/lib/pingularity/pingularity.db"]