Using Bake with additional contexts
In addition to the main context
key that defines the build context, each
target can also define additional named contexts with a map defined with key
contexts
. These values map to the --build-context
flag in the
build
command.
Inside the Dockerfile these contexts can be used with the FROM
instruction or
--from
flag.
Supported context values are:
- Local filesystem directories
- Container images
- Git URLs
- HTTP URLs
- Name of another target in the Bake file
Pinning alpine image
# syntax=docker/dockerfile:1
FROM alpine
RUN echo "Hello world"
# docker-bake.hcl
target "app" {
contexts = {
alpine = "docker-image://alpine:3.13"
}
}
Using a secondary source directory
# syntax=docker/dockerfile:1
FROM scratch AS src
FROM golang
COPY --from=src . .
# docker-bake.hcl
target "app" {
contexts = {
src = "../path/to/source"
}
}
Using a target as a build context
To use a result of one target as a build context of another, specify the target
name with target:
prefix.
# syntax=docker/dockerfile:1
FROM baseapp
RUN echo "Hello world"
# docker-bake.hcl
target "base" {
dockerfile = "baseapp.Dockerfile"
}
target "app" {
contexts = {
baseapp = "target:base"
}
}
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:
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
:
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
.
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