Skip to content

builder: Proposal: Add support for RUN --mount #32507

Closed
@tonistiigi

Description

This proposal is a combined from the previous discussion in #30110 #3056 #5369 #31067 (comment) #30449
, from @justincormack @duglin and many others.

I propose adding an extra flag --mount to the RUN command in Dockerfile. This would make sure that certain external resources are present while the build step runs. These mounts will not end up in the final image.

Build cache for every RUN would be calculated same way as multi-stage build COPY --from= is implemented. The builder would calculate a secure hash for the source directory and validate if it is the same as in the previous invocation. If something changes in the mounted directory the RUN command executes again.

Use cases:

Avoid copying over files that are just needed for a build command and don't need to be in the final image. Simple example is

COPY dir /
RUN go build -o d ./dir

In that case, the source does not need to be copied(and potentially deleted) into the image. Instead the process could use it directly: RUN --mount=src=/dst,destination=/dst,ro=true go build ....

Mounts can also appear from other build stages using the same logic as COPY --from.

FROM debian AS foo
...
FROM alpine
RUN --mount=src=/,target=foo,from=foo ..

This can also be used as a workaround for the COPY --chown issue as with mounting, no extra layer is created between copy and any other operation running in the container. chown isn't a primary use case for it though, and maybe should be supported separately as well.

Mounts from other images can only be read-only.

Optional additional use case: tmpfs

If a command needs a place to store temporary files it would be good if it could just set some directory as tmpfs instead of trying to clean up after itself and doing unnecessary disk accesses.

RUN --mount=target=foo,type=tmpfs.

In the future, we could allow more types. It is necessary though that we don't allow anything that isn't reproducible or uses some external resource.

Optional additional use case: shared build cache

There is a widely requested feature for providing a way to have shared cache directories between builder invocations. Usually, people would want to work around it by introducing -v to docker build but that has many downsides #31499 (comment)

A solution for that could be to allow exposing a special kind of mount that is mutable and can be automatically cleared by the builder.

FROM scratch AS cache-for-go

FROM golang
RUN --mount=target=/go/pkg,from=cache-for-go,type=cache go build

Now everything written to /go/pkg by go would be already there next time builder runs(unless user runs docker system prune). The cache ID could be calculated after the program has executed, or maybe, in this case, it would be users responsibility to make sure that all data in this directory is optional and cache would only be invalidated if commands in cache-for–go definition change. Finding previous cache directory would be based on session ID from client like in #31829

@dnephin @justincormack @duglin @tiborvass @vdemeester

Activity

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

Metadata

Assignees

No one assigned

    Labels

    area/builderarea/builder/buildkitIssues affecting buildkitkind/featureFunctionality or other elements that the project doesn't currently have. Features are new and shiny

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions