From 0cbda2e5264414cc148185d1577d8080983cd2e9 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 15 Sep 2023 17:29:20 +0900 Subject: [PATCH] Dockerfile: add ALPINE_CACHE image to lock apk versions The `ALPINE_CACHE` image contains `/etc/apk/cache` for apk files referred from the entire Dockerfile. All the `apk add` commands in the Dockerfile are now executed with the mount for `ALPINE_CACHE` and with `--no-network`. The `ALPINE_CACHE` image defaults to the `alpine-cache-local` stage, but can be also set to `docker.io/moby/buildkit:${RELEASE}-alpine-cache` for reproducibility. Signed-off-by: Akihiro Suda --- .github/workflows/buildkit.yml | 1 + .github/workflows/buildx-image.yml | 1 + Dockerfile | 83 +++++++++++++++++++++++++----- apklist | 33 ++++++++++++ docker-bake.hcl | 5 ++ 5 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 apklist diff --git a/.github/workflows/buildkit.yml b/.github/workflows/buildkit.yml index 8c655a1bae6a..ba8347399549 100644 --- a/.github/workflows/buildkit.yml +++ b/.github/workflows/buildkit.yml @@ -146,6 +146,7 @@ jobs: target-stage: - '' - rootless + - alpine-cache steps: - name: Checkout diff --git a/.github/workflows/buildx-image.yml b/.github/workflows/buildx-image.yml index cd9ed3eb7b87..682694a916a3 100644 --- a/.github/workflows/buildx-image.yml +++ b/.github/workflows/buildx-image.yml @@ -42,6 +42,7 @@ jobs: flavor: - '' - 'rootless' + - 'alpine-cache' steps: - name: Set up Docker Buildx diff --git a/Dockerfile b/Dockerfile index 70fbf0933917..edb6211ff3d8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,33 +19,82 @@ ARG GOTESTSUM_VERSION=v1.9.0 ARG GO_VERSION=1.20 ARG ALPINE_VERSION=3.18 +# ALPINE_CACHE defaults to the "alpine-cache-local" stage in this image. +# Can be overridden to a custom image for reproducible builds. +ARG ALPINE_CACHE=alpine-cache-local + # minio for s3 integration tests FROM minio/minio:${MINIO_VERSION} AS minio FROM minio/mc:${MINIO_MC_VERSION} AS minio-mc # alpine base for buildkit image # TODO: remove this when alpine image supports riscv64 -FROM alpine:${ALPINE_VERSION} AS alpine-amd64 -FROM alpine:${ALPINE_VERSION} AS alpine-arm -FROM alpine:${ALPINE_VERSION} AS alpine-arm64 -FROM alpine:${ALPINE_VERSION} AS alpine-s390x -FROM alpine:${ALPINE_VERSION} AS alpine-ppc64le -FROM alpine:edge@sha256:2d01a16bab53a8405876cec4c27235d47455a7b72b75334c614f2fb0968b3f90 AS alpine-riscv64 +FROM --platform=amd64 alpine:${ALPINE_VERSION} AS alpine-amd64 +FROM --platform=arm alpine:${ALPINE_VERSION} AS alpine-arm +FROM --platform=arm64 alpine:${ALPINE_VERSION} AS alpine-arm64 +FROM --platform=s390x alpine:${ALPINE_VERSION} AS alpine-s390x +FROM --platform=ppc64le alpine:${ALPINE_VERSION} AS alpine-ppc64le +FROM --platform=riscv64 alpine:edge@sha256:2d01a16bab53a8405876cec4c27235d47455a7b72b75334c614f2fb0968b3f90 AS alpine-riscv64 FROM alpine-$TARGETARCH AS alpinebase +FROM --platform=$BUILDPLATFORM alpine AS alpinebase-buildplatform # xx is a helper for cross-compilation FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.2.1 AS xx +FROM alpinebase AS alpine-cache-local-targetplatform +RUN --mount=source=./apklist,target=/apklist \ + mkdir -p /etc/apk/cache && apk update && apk cache download --available --add-dependencies $(grep -v '^#' /apklist) + +FROM alpinebase-buildplatform AS alpine-cache-local-buildplatform +RUN --mount=source=./apklist,target=/apklist \ + mkdir -p /etc/apk/cache && apk update && apk cache download --available --add-dependencies $(grep -v '^#' /apklist) + +FROM scratch AS alpine-cache-local +COPY --from=alpine-cache-local-targetplatform /etc/apk/cache /etc/apk/cache + +# alpine-cache is the stage to collect apk cache files. +# This stage can be pushed for sake of reproducible builds. +FROM $ALPINE_CACHE AS alpine-cache +FROM --platform=amd64 alpine-cache AS alpine-cache-amd64 +FROM --platform=arm alpine-cache AS alpine-cache-arm +FROM --platform=arm64 alpine-cache AS alpine-cache-arm64 +FROM --platform=s390x alpine-cache AS alpine-cache-s390x +FROM --platform=ppc64le alpine-cache AS alpine-cache-ppc64le +FROM --platform=riscv64 alpine-cache AS alpine-cache-riscv64 +FROM --platform=$TARGETPLATFORM alpine-cache-${TARGETARCH} AS alpine-cache-targetplatform +# NOTE: when $ALPINE_CACHE is set to alpine-cache-local, alpine-cache-remote-buildplatform is invalid, +# as alpine-cache-${BUILDARCH} is built from the TARGETPLATFORM image +FROM --platform=$BUILDPLATFORM alpine-cache-${BUILDARCH} AS alpine-cache-remote-buildplatform + +FROM --platform=$BUILDPLATFORM alpinebase-buildplatform AS alpine-cache-xx +ARG BUILDPLATFORM +COPY --link --from=alpine-cache-remote-buildplatform /etc/apk/cache /etc/apk/cache/_remote_buildplatform +COPY --link --from=alpine-cache-local-buildplatform /etc/apk/cache /etc/apk/cache/_local_buildplatform +ARG ALPINE_CACHE +RUN <> /home/user/.profile \ && mkdir -m 0700 -p /run/user/1000 \ @@ -264,7 +317,8 @@ ARG NERDCTL_VERSION RUN curl -Ls https://raw.githubusercontent.com/containerd/nerdctl/$NERDCTL_VERSION/extras/rootless/containerd-rootless.sh > /usr/bin/containerd-rootless.sh \ && chmod 0755 /usr/bin/containerd-rootless.sh ARG AZURITE_VERSION -RUN apk add --no-cache nodejs npm \ +RUN --mount=from=alpine-cache-xx,source=/etc/apk/cache,target=/etc/apk/cache,rw \ + apk add --no-network nodejs npm \ && npm install -g azurite@${AZURITE_VERSION} # The entrypoint script is needed for enabling nested cgroup v2 (https://github.com/moby/buildkit/issues/3265#issuecomment-1309631736) RUN curl -Ls https://raw.githubusercontent.com/moby/moby/v20.10.21/hack/dind > /docker-entrypoint.sh \ @@ -301,7 +355,8 @@ VOLUME /var/lib/buildkit # Rootless mode. FROM alpinebase AS rootless -RUN apk add --no-cache fuse3 fuse-overlayfs git openssh pigz shadow-uidmap xz +RUN --mount=from=alpine-cache-targetplatform,source=/etc/apk/cache,target=/etc/apk/cache,rw \ + apk add --no-network fuse3 fuse-overlayfs git openssh pigz shadow-uidmap xz RUN adduser -D -u 1000 user \ && mkdir -p /run/user/1000 /home/user/.local/tmp /home/user/.local/share/buildkit \ && chown -R user /run/user/1000 /home/user \ diff --git a/apklist b/apklist new file mode 100644 index 000000000000..6f909e7d8dcd --- /dev/null +++ b/apklist @@ -0,0 +1,33 @@ +# List of apks to be cached in moby/buildkit:${RELEASE}-alpine-cache for reproducibility +bash +clang +curl +dnsmasq +file +fuse +fuse3 +fuse-overlayfs +gcc +git +git-daemon +gzip +iptables +ip6tables +libseccomp-dev +libseccomp-static +lld +make +musl-dev +nodejs +npm +openssh +openssh-client +pkgconfig +pigz +shadow +shadow-uidmap +sudo +tar +vim +xz +zlib diff --git a/docker-bake.hcl b/docker-bake.hcl index 89557afaef6d..7cc13955ad3b 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -2,6 +2,10 @@ variable "ALPINE_VERSION" { default = null } +variable "ALPINE_CACHE" { + default = null +} + variable "GO_VERSION" { default = null } @@ -26,6 +30,7 @@ function "bindir" { target "_common" { args = { ALPINE_VERSION = ALPINE_VERSION + ALPINE_CACHE = ALPINE_CACHE GO_VERSION = GO_VERSION NODE_VERSION = NODE_VERSION BUILDKIT_CONTEXT_KEEP_GIT_DIR = 1