使用Bake与额外的上下文

除了定义构建上下文的主要context键之外,每个目标还可以使用键contexts定义的映射来定义额外的命名上下文。这些值映射到构建命令中的--build-context标志。

在Dockerfile中,这些上下文可以与FROM指令或--from标志一起使用。

支持的上下文值为:

  • 本地文件系统目录
  • 容器镜像
  • Git URLs
  • HTTP 网址
  • Bake 文件中另一个目标的名称

固定Alpine镜像

# syntax=docker/dockerfile:1
FROM alpine
RUN echo "Hello world"
# docker-bake.hcl
target "app" {
  contexts = {
    alpine = "docker-image://alpine:3.13"
  }
}

使用辅助源目录

# syntax=docker/dockerfile:1
FROM scratch AS src

FROM golang
COPY --from=src . .
# docker-bake.hcl
target "app" {
  contexts = {
    src = "../path/to/source"
  }
}

使用目标作为构建上下文

要将一个目标的结果用作另一个目标的构建上下文,请使用target:前缀指定目标名称。

# syntax=docker/dockerfile:1
FROM baseapp
RUN echo "Hello world"
# docker-bake.hcl
target "base" {
  dockerfile = "baseapp.Dockerfile"
}

target "app" {
  contexts = {
    baseapp = "target:base"
  }
}

在大多数情况下,您应该只使用一个具有多个目标的多阶段Dockerfile来实现类似的行为。仅当您有多个无法轻松合并为一个的Dockerfile时,才建议使用此情况。

去重上下文传输

注意

从Buildx版本0.17.0及以后开始,Bake会自动去重共享相同上下文的目标的上下文传输。除了Buildx版本0.17.0外,构建器必须运行BuildKit版本0.16.0或更高版本,并且Dockerfile语法必须是docker/dockerfile:1.10或更高版本。

如果您满足这些要求,您不需要手动去重上下文传输,如本节所述。

  • 要检查您的Buildx版本,请运行docker buildx version
  • 要检查您的BuildKit版本,请运行docker buildx inspect --bootstrap并查找BuildKit version字段。
  • 要检查您的Dockerfile语法版本,请检查Dockerfile中的syntax解析器指令。如果不存在,则默认版本是当前BuildKit版本附带的版本。要明确设置版本,请在Dockerfile顶部添加#syntax=docker/dockerfile:1.10

当你使用组并发构建目标时,每个目标的构建上下文是独立加载的。如果同一个上下文被组中的多个目标使用,那么每次使用该上下文时都会传输一次。这可能会对构建时间产生重大影响,具体取决于你的构建配置。例如,假设你有一个Bake文件,定义了以下目标组:

group "default" {
  targets = ["target1", "target2"]
}

target "target1" {
  target = "target1"
  context = "."
}

target "target2" {
  target = "target2"
  context = "."
}

在这种情况下,当你构建默认组时,上下文 . 被传递了两次:一次用于 target1,一次用于 target2

如果你的上下文很小,并且你使用的是本地构建器,重复的上下文传输可能不是什么大问题。但如果你的构建上下文很大,或者你有大量的目标,或者你正在通过网络将上下文传输到远程构建器,上下文传输就会成为性能瓶颈。

为了避免多次传输相同的上下文,你可以定义一个只加载上下文文件的命名上下文,并让每个需要这些文件的目标引用该命名上下文。例如,以下Bake文件定义了一个名为ctx的目标,它被target1target2同时使用:

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"
  }
}

命名的上下文 ctx 代表一个 Dockerfile 阶段,它从其上下文 (.) 复制文件。Dockerfile 中的其他阶段现在可以引用 ctx 命名的上下文,并且例如,使用 --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