Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dockerfile: add ALPINE_CACHE image to lock apk versions #4238

Closed
wants to merge 1 commit into from

Conversation

AkihiroSuda
Copy link
Member

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.

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
Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

I think you need to set the base first with build platform:

FROM --platform=$BUILDPLATFORM alpine:${ALPINE_VERSION} AS alpine
FROM alpine AS alpine-amd64
...

Pretty much like https://github.com/moby/moby/pull/44735/files#diff-dd2c0eb6ea5cfc6c4bd4eac30934e2d5746747af48fef6da689e85b752f39557R40-R52

Dockerfile Outdated
# alpine-cache-local is the stage to collect apk cache files.
# This stage can be pushed for sake of reproducible builds.
FROM scratch AS alpine-cache-local
COPY --from=alpine-cache-local-base /etc/apk/cache /etc/apk/cache
Copy link
Member Author

Choose a reason for hiding this comment

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

Eventually we want to "unsquash" the /etc/apk/cache layer to multiple layers in the apk file granularity to help deduplicating the layer blobs:

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 <akihiro.suda.cz@hco.ntt.co.jp>
@AkihiroSuda AkihiroSuda marked this pull request as ready for review September 15, 2023 12:13
Copy link
Member

@tonistiigi tonistiigi left a comment

Choose a reason for hiding this comment

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

This looks like way too much extra work for a very custom behavior. I think instead, we should a "material-attestation" and that would save the snapshots. Currently, in provenance we have digests for the materials, but we could also have a separate manifest that would allow pulling all these digests from the registry.

@AkihiroSuda
Copy link
Member Author

AkihiroSuda commented Sep 15, 2023

This looks like way too much extra work for a very custom behavior. I think instead, we should a "material-attestation" and that would save the snapshots. Currently, in provenance we have digests for the materials, but we could also have a separate manifest that would allow pulling all these digests from the registry.

Could you elaborate? How will the Dockerfile and the build command look like?

@tonistiigi
Copy link
Member

tonistiigi commented Sep 15, 2023

I think we've discussed this in the past. Maybe in slack. For alpine you would need something like https://github.com/tonistiigi/buildkit-alpine . Eg. this is an example image https://explore.ggcr.dev/?image=tonistiigi%2Ftest:alpine-curl . If you look at the provenance attestation then there are individual alpine packages all there with their checksums. The missing piece would be to also push the blobs to the registry and then you can use the source policy rule that converts from https URL or apk package into the same blob in registry.

image image

@AkihiroSuda
Copy link
Member Author

I think we've discussed this in the past. Maybe in slack. For alpine you would need something like https://github.com/tonistiigi/buildkit-alpine .

Yes, but how is this expected to be integrated to the Dockerfile syntax?
I also wonder how we can make this portable to other package managers, while keeping the syntax as simple as possible.

@tonistiigi
Copy link
Member

Yes, but how is this expected to be integrated to the Dockerfile syntax?

You can use --build-context (or FROM) and longer term we need to figure out how to link frontends together with a nicer UI (maybe smth like FROM ./alpine.yml AS alpine)

@tonistiigi
Copy link
Member

I also wonder how we can make this portable to other package managers,

For anything that gets too custom in the package manger territory, it is easier to implement such things with full frontend API rather that let the user hack something together with Dockerfile limitations. We get lot of consistency for free like provenance materials detection and verification, unified storage and automatic snapshot loading from previous provenance via source policies. Doing this by hand doesn't have any of such guarantees/features.

@tonistiigi
Copy link
Member

Copying what we discussed in Slack here:

Example:

  1. we make a buildkit release and push an image
  2. a 3rd party downloads provenance for our release
  3. it can now pull all the materials in that provenance and verify them offline if it wants to
  4. it issues a rebuild with a special policy that doesn’t allow any outside images or new materials not in the policy. It can also drop the network completely.
  5. it checks if it got the same artifact digest
  6. if it did, then it issues a new (signed) attestation, confirming that our provenance was correct and is based only on our strictly defined sources
  7. our image is now more trustworthy because trusted parties not related to us have verified it. It is impossible it was built from a a different Git commit or used apk package with a CVE for example.

@AkihiroSuda
Copy link
Member Author

AkihiroSuda commented Sep 16, 2023

Alternatively, we may just support OCI exporter for cache mounts and call it a day.

Dockerfile:

FROM alpine:3.18@sha256:deadbeef
RUN --mount=type=cache,target=/etc/apk/cache,id=etc-apk-cache \
  apk add gcc

Push:

# orasify=true ORAS-ifies the cache blobs for deduplication. 
# (1 blob = 1 apk file)
# This option should be optional.
docker buildx build . \
  --push \
  -t example.com/myimage:v1.2.3 \
  --cache-to type=oci,orasify=true,cache-mount-id=etc-apk-cache,target=example.com/myimage:v1.2.3-etc-apk-cache

Repro:

docker buildx build . \
  --cache-from type=oci,cache-mount-id=etc-apk-cache,src=example.com/myimage:v1.2.3-etc-apk-cache

@AkihiroSuda
Copy link
Member Author

Opened an issue to continue the discussion

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants