diff --git a/content/build/bake/contexts.md b/content/build/bake/contexts.md index 8b2744cd289..86bc55e3f9e 100644 --- a/content/build/bake/contexts.md +++ b/content/build/bake/contexts.md @@ -88,3 +88,85 @@ target "app" { In most cases you should just use a single multi-stage Dockerfile with multiple targets for similar behavior. This case is only recommended when you have multiple Dockerfiles that can't be easily merged into one. + +## Deduplicate context transfer + +When you build targets concurrently, using groups, build contexts are loaded +independently for each target. If the same context is used by multiple targets +in a group, that context is transferred once for each time it's used. This can +result in significant impact on build time, depending on your build +configuration. For example, say you have a Bake file that defines the following +group of targets: + +```hcl +group "default" { + targets = ["target1", "target2"] +} + +target "target1" { + target = "target1" + context = "." +} + +target "target2" { + target = "target2" + context = "." +} +``` + +In this case, the context `.` is transferred twice when you build the default +group: once for `target1` and once for `target2`. + +If your context is small, and if you are using a local builder, duplicate +context transfers may not be a big deal. But if your build context is big, or +you have a large number of targets, or you're transferring the context over a +network to a remote builder, context transfer becomes a performance bottleneck. + +To avoid transferring the same context multiple times, you can define a named +context that only loads the context files, and have each target that needs +those files reference that named context. For example, the following Bake file +defines a named target `ctx`, which is used by both `target1` and `target2`: + +```hcl +group "default" { + targets = ["target1", "target2"] +} + +target "ctx" { + context = "." + target = "ctx" +} + +target "target1" { + target = "target1" + contexts = { + ctx = "target:ctx" + } +} + +target "target2" { + target = "target2" + contexts = { + ctx = "target:ctx" + } +} +``` + +The named context `ctx` represents a Dockerfile stage, which copies the files +from its context (`.`). Other stages in the Dockerfile can now reference the +`ctx` named context and, for example, mount its files with `--mount=from=ctx`. + +```dockerfile +FROM scratch AS ctx +COPY --link . . + +FROM golang:alpine AS target1 +WORKDIR /work +RUN --mount=from=ctx \ + go build -o /out/client ./cmd/client \ + +FROM golang:alpine AS target2 +WORKDIR /work +RUN --mount=from=ctx \ + go build -o /out/server ./cmd/server +```