concourse/oci-build-task

"RUN --mount=type=cache" caches not persisted

charles-dyfis-net opened this issue · 3 comments

This isn't a request for a code change as much as for documentation, presuming that there is in fact a reasonable way to reuse the ./cache directory for arbitrary user-provided content from inside the container. If there isn't, then this might be into feature-request territory (which I'd be happy to take a shot at if given some guidance about what an implementation would look like).

Insofar as oci-build-task uses Buildkit, extended syntax is available in Dockerfiles using it; for example:

RUN --mount=type=cache,target=/go-cache env GOCACHE=/go-cache go build

(similar use cases include Maven jar caches, Nix store caches, etc).

Unfortunately, even with caches: [{"path": "cache"}] enabled, this doesn't actually work to reuse downloaded Go modules across builds -- there's an error of the form:

 (*service).Write failed                       error="rpc error: code = Canceled desc = context canceled

...and as far as I can tell, the ./cache directory isn't mapped into the container context.

Is there a reasonable way to cache content inside of oci-build-task?

The relevant issue in buildkit - moby/buildkit#1512

To sum up, buildkit type=cache mounts are not considered an image layers, and are not exported by the buildkit's --export-cache functionality on which the oci-build-task relies. There are some workarounds suggested, which imply running of two extra build operations (possibly defined in a separate Dockerfile(s)):

  • first - to import the cache contents into the type=cache mounts
  • second - to export type=cache mounts contents out into some persistent storage

Implementation details could vary, should it rely on docker layer caching, CI caching functionality, or just use rclone to sync the volumes with S3/whatever.

Also, there is one a quite different suggestion, which looks more like a real solution to the problem. It proposes to use a dedicated buildkitd server, which would execute actual container build jobs, and clients inside the CI jobs would only send a context to it. I like this solution, but not sure this fits well into the Concourse philosophy.