samrocketman / blog

A personal technical blog. Full featured complete with automated peer review.
http://sam.gleske.net/blog/
Other
5 stars 0 forks source link

Distroless busybox #81

Open samrocketman opened 1 year ago

samrocketman commented 1 year ago

A minimal distroless busybox

FROM alpine

SHELL ["/bin/sh", "-exc"]
# Prerequisites
RUN \
  # Directory structure and permissions
  mkdir -p base/bin base/tmp base/var/tmp base/etc base/home/nonroot base/sbin base/root; \
  chmod 700 /root; \
  chown root:root /root; \
  chmod 1777 base/tmp base/var/tmp; \
  chown 65532:65532 base/home/nonroot; \
  chmod 750 base/home/nonroot; \
  # UID and GID
  echo 'root:x:0:' > /base/etc/group; \
  echo 'nonroot:x:65532:' >> /base/etc/group; \
  echo 'root:x:0:0:root:/root:/sbin/nologin' > /base/etc/passwd; \
  echo 'nonroot:x:65532:65532:nonroot:/home/nonroot:/sbin/nologin' >> /base/etc/passwd; \
  # init binary
  apk add --no-cache dumb-init; \
  cp -a /usr/bin/dumb-init base/bin/dumb-init; \
  # copy busybox and musl
  mkdir -p base/usr/bin base/lib; \
  cp /lib/ld-musl-*.so.1 base/lib; \
  cp -a /bin/busybox base/bin/; \
  # find all symlinks pointing at busybox
  for x in /bin /sbin /usr/bin /usr/sbin; do \
    mkdir -p base"$x"; \
    find "$x" -type l -exec /bin/sh -c 'e() { if [ "`readlink "$1"`" = /bin/busybox ]; then echo "$1"; fi; }; e {}' \; \
      | tr '\n' '\0' | xargs -0 -I{} cp -a {} base"$x"/; \
  done; \
  echo "distroless" > base/etc/issue

FROM scratch
COPY --from=0 /base/ /
ENTRYPOINT ["/bin/dumb-init", "--"]
USER nonroot
ENV HOME=/home/nonroot USER=nonroot PATH="/usr/sbin:/usr/bin:/sbin:/bin"
WORKDIR /home/nonroot
CMD ["/bin/sh"]
samrocketman commented 10 months ago

I've written a script which makes copying binaries and their shared object dependencies easier.

copy-bin.sh -p /base --ldd /bin/busybox --links /bin:/sbin:/usr/bin:/usr/sbin

Alternate Dockerfile using copy-bin.sh

FROM alpine

SHELL ["/bin/sh", "-exc"]
# copy-bin.sh provides easy ability to copy binaries with shared object dependencies
RUN \
  wget -qO /usr/local/bin/copy-bin.sh https://raw.githubusercontent.com/samrocketman/home/main/bin/copy-bin.sh; \
  chmod 755 /usr/local/bin/copy-bin.sh

# Distroless hierarchy
RUN \
  # Directory structure and permissions
  mkdir -p base/bin base/tmp base/var/tmp base/etc base/home/nonroot base/sbin base/root; \
  chmod 700 /root; \
  chown root:root /root; \
  chmod 1777 base/tmp base/var/tmp; \
  chown 65532:65532 base/home/nonroot; \
  chmod 750 base/home/nonroot; \
  # UID and GID 
  echo 'root:x:0:' > /base/etc/group; \
  echo 'nonroot:x:65532:' >> /base/etc/group; \
  echo 'root:x:0:0:root:/root:/sbin/nologin' > /base/etc/passwd; \
  echo 'nonroot:x:65532:65532:nonroot:/home/nonroot:/sbin/nologin' >> /base/etc/passwd; \
  # init binary
  apk add --no-cache dumb-init; \
  cp -a /usr/bin/dumb-init base/bin/dumb-init; \
  echo "distroless" > base/etc/issue

# Add busybox shell to distroless distribution
RUN \
  copy-bin.sh -p /base --ldd /bin/busybox --links /bin:/sbin:/usr/bin:/usr/sbin

FROM scratch
COPY --from=0 /base/ /
ENTRYPOINT ["/bin/dumb-init", "--"]
USER nonroot
ENV HOME=/home/nonroot USER=nonroot PATH="/usr/sbin:/usr/bin:/sbin:/bin"
WORKDIR /home/nonroot
CMD ["/bin/sh"]
samrocketman commented 10 months ago

Example copy-bin.sh where bash is copied into a container from scratch.

copy-bin.sh -p "$PWD"/base --ldd /bin/bash
docker build -f Dockerfile -t bash base
docker run --init -it --rm bash /bin/bash

Where Dockerfile is

FROM scratch
COPY . /