Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions telegraf/1.39/distroless/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Telegraf on scratch: the static (CGO_ENABLED=0) binary plus only the runtime
# files it needs: no shell, package manager, or OS userland. The alpine stage
# GPG-verifies the release and assembles the exact final image tree under
# /rootfs; the scratch stage is a single COPY of it.

ARG TELEGRAF_VERSION=1.39.1
Comment thread
skartikey marked this conversation as resolved.

FROM alpine:3.23 AS fetch
ARG TELEGRAF_VERSION

RUN set -eux; \
case "$(apk --print-arch)" in \
x86_64) ARCH='amd64';; \
aarch64) ARCH='arm64';; \
*) echo "Unsupported architecture: $(apk --print-arch)" >&2; exit 1;; \
esac; \
apk add --no-cache ca-certificates tzdata wget gnupg tar; \
update-ca-certificates; \
mkdir -p ~/.gnupg; echo "disable-ipv6" >> ~/.gnupg/dirmngr.conf; \
gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 24C975CBA61A024EE1B631787C3D57159FC2F927; \
base="telegraf-${TELEGRAF_VERSION}_linux_${ARCH}.tar.gz"; \
wget --no-verbose "https://dl.influxdata.com/telegraf/releases/${base}"; \
wget --no-verbose "https://dl.influxdata.com/telegraf/releases/${base}.asc"; \
gpg --batch --verify "${base}.asc" "${base}"; \
mkdir -p /src /rootfs/usr/bin /rootfs/etc/telegraf /rootfs/etc/ssl/certs /rootfs/usr/share; \
tar -C /src -xzf "${base}"; \
# Copy from the explicit `telegraf-<v>/` prefix: release tar roots vary (some
# add a leading ./), which makes a fixed --strip-components unreliable.
src="/src/telegraf-${TELEGRAF_VERSION}"; \
cp -a "${src}/usr/bin/telegraf" /rootfs/usr/bin/telegraf; \
cp -a "${src}/etc/telegraf/telegraf.conf" /rootfs/etc/telegraf/telegraf.conf; \
cp -a "${src}/etc/telegraf/telegraf.d" /rootfs/etc/telegraf/telegraf.d; \
cp /etc/ssl/certs/ca-certificates.crt /rootfs/etc/ssl/certs/ca-certificates.crt; \
cp -a /usr/share/zoneinfo /rootfs/usr/share/zoneinfo; \
# Resolve hostnames via /etc/hosts before DNS.
printf 'hosts: files dns\n' > /rootfs/etc/nsswitch.conf; \
# Lets pure-Go os/user (CGO_ENABLED=0) map uid 65532 to a name; without it
# lookups like procstat's user tag fail silently. USER below sets the identity.
# We name the account "telegraf" (matching the alpine image) but keep the uid
# 65532 (the distroless "nonroot" uid), NOT 65534/nobody: 65534 is the
# kernel overflow uid, the id that unmapped user-namespace ids and NFS root-squash
# collapse to, so running as it would make telegraf indistinguishable from a
# failed-to-map process to security/monitoring tooling. 65532 sits outside that.
# overflow uid default 65534: https://www.kernel.org/doc/html/latest/admin-guide/sysctl/kernel.html
# unmapped userns id -> overflow: https://man7.org/linux/man-pages/man7/user_namespaces.7.html
# distroless nonroot = 65532: https://github.com/GoogleContainerTools/distroless/blob/main/common/variables.bzl
# (nobody is kept in the map so 65534-owned files still resolve; we just never run as it.)
printf 'root:x:0:0:root:/root:/sbin/nologin\nnobody:x:65534:65534:nobody:/nonexistent:/sbin/nologin\ntelegraf:x:65532:65532:telegraf:/home/telegraf:/sbin/nologin\n' > /rootfs/etc/passwd; \
printf 'root:x:0:\nnobody:x:65534:\ntelegraf:x:65532:\n' > /rootfs/etc/group; \
# /tmp is 1777 (world-writable + sticky) so a container running under an
# arbitrary uid (e.g. the random uid OpenShift's default SCC assigns) gets a
# writable /tmp, not just uid 65532. BuildKit, which official-images publishes
# with, preserves this mode through COPY; buildah does too.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[question] An earlier revision said buildah doesn't keep mode bits through COPY, and now this line and line 77 say it does. Did you test that with buildah, or was it just reworded? If it wasn't tested, I'd only mention BuildKit here.

# /home/telegraf stays 65532-owned; telegraf needs no writable HOME.
# Numeric id in chown, not "telegraf": the alpine stage's /etc/passwd has no
# telegraf user, so a BusyBox name lookup would fail ("unknown user/group") and
# abort under set -eux; a numeric id skips the lookup.
# https://github.com/vda-linux/busybox_mirror/blob/ec0c5cc142f1f9ea57235df5d093fbe180ad9c7d/libpwdgrp/uidgid_get.c#L77-L80
mkdir -p /rootfs/home/telegraf /rootfs/tmp; \
chown 65532:65532 /rootfs/home/telegraf /rootfs/tmp; \
chmod 1777 /rootfs/tmp

FROM scratch

ARG TELEGRAF_VERSION
ENV TELEGRAF_VERSION=${TELEGRAF_VERSION}
LABEL org.opencontainers.image.title="telegraf" \
org.opencontainers.image.description="Distroless Telegraf: static binary on scratch (no shell, no OS userland, non-root)" \
org.opencontainers.image.version="${TELEGRAF_VERSION}" \
org.opencontainers.image.source="https://github.com/influxdata/influxdata-docker" \
org.opencontainers.image.base.name="scratch" \
org.opencontainers.image.vendor="InfluxData Inc." \
org.opencontainers.image.licenses="MIT"

# The whole rootfs was staged and GPG-verified in the fetch stage; one COPY
# brings it over. Ownership (incl. the 65532-owned /home/telegraf and /tmp) is
# preserved by docker, podman, and buildah alike.
COPY --from=fetch /rootfs/ /

ENV HOME=/home/telegraf

# Numeric, not a name: with runAsNonRoot=true the kubelet reads the image's USER
# field directly (never its /etc/passwd), so a named user fails admission
# ("cannot verify user is non-root"). 65532 is the distroless "nonroot" uid,
# which we name "telegraf" in the image's /etc/passwd.
# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/kuberuntime/security_context_others.go#L50
USER 65532:65532

ENTRYPOINT ["/usr/bin/telegraf"]
Comment thread
skartikey marked this conversation as resolved.
CMD ["--config", "/etc/telegraf/telegraf.conf", "--config-directory", "/etc/telegraf/telegraf.d"]
10 changes: 10 additions & 0 deletions telegraf/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@
"amd64",
"arm64v8"
]
},
{
"name": "distroless",
"versions": [
"1.39"
Comment thread
skartikey marked this conversation as resolved.
],
"architectures": [
"amd64",
"arm64v8"
]
}
]
}