构建上下文
和 命令从中构建 Docker 镜像
一个 Dockerfile 和一个上下文。docker build
docker buildx build
什么是构建上下文?
构建上下文是构建可以访问的一组文件。 传递给 build 命令的 positional 参数指定 context 中:
$ docker build [OPTIONS] PATH | URL | -
^^^^^^^^^^^^^^
您可以将以下任何输入作为构建的上下文传递:
- 本地目录的相对或绝对路径
- Git 存储库、tarball 或纯文本文件的远程 URL
- 通过标准输入通过管道传输到命令的纯文本文件或 tarball
docker build
文件系统上下文
当您的构建上下文是本地目录、远程 Git 存储库或 tar 时
文件,则它将成为生成器可以在
建。构建指令(如 和 )可以引用任何
文件中的文件和目录。COPY
ADD
文件系统构建上下文以递归方式处理:
- 当您指定本地目录或 tarball 时,所有子目录都包含在内
- 指定远程 Git 存储库时,将包含存储库和所有子模块
有关您 可以与你的版本一起使用,请参阅:
文本文件上下文
当您的构建上下文是纯文本文件时,构建器会解释该文件 作为 Dockerfile 进行。使用这种方法,构建不使用文件系统上下文。
有关更多信息,请参阅空构建上下文。
本地上下文
要使用本地构建上下文,您可以指定相对或绝对文件路径
添加到命令中。以下示例显示了一个生成命令,该命令
使用当前目录 () 作为构建上下文:docker build
.
$ docker build .
...
#16 [internal] load build context
#16 sha256:23ca2f94460dcbaf5b3c3edbaaa933281a4e0ea3d92fe295193e4df44dc68f85
#16 transferring context: 13.16MB 2.2s done
...
这使得当前工作目录中的文件和目录可供 构建器。在以下情况下,构建器会从构建上下文中加载所需的文件 需要。
你也可以使用本地 tarball 作为构建上下文,方法是将 tarball 管道化
contents 添加到命令中。参见 Tarballs。docker build
本地目录
请考虑以下目录结构:
.
├── index.ts
├── src/
├── Dockerfile
├── package.json
└── package-lock.json
如果 Dockerfile 指令可以引用这些文件并将其包含在构建中,则 将此目录作为上下文传递。
# syntax=docker/dockerfile:1
FROM node:latest
WORKDIR /src
COPY package.json package-lock.json .
RUN npm ci
COPY index.ts src .
$ docker build .
带有 stdin 的 Dockerfile 的本地上下文
使用以下语法使用本地 filesystem,同时使用 stdin 中的 Dockerfile。
$ docker build -f- <PATH>
语法使用 -f(或 --file)选项来指定要使用的 Dockerfile,并且 它使用连字符 (-) 作为文件名,指示 Docker 从 stdin 的
以下示例使用当前目录 (.) 作为构建上下文,并且 使用 here-document 通过 stdin 传递的 Dockerfile 构建镜像。
# create a directory to work in
mkdir example
cd example
# create an example file
touch somefile.txt
# build an image using the current directory as context
# and a Dockerfile passed through stdin
docker build -t myimage:latest -f- . <<EOF
FROM busybox
COPY somefile.txt ./
RUN cat /somefile.txt
EOF
本地 tarball
当您通过管道将 tarball 传递给 build 命令时,构建使用 将 tarball 作为 filesystem 上下文。
例如,给定以下项目目录:
.
├── Dockerfile
├── Makefile
├── README.md
├── main.c
├── scripts
├── src
└── test.Dockerfile
您可以创建目录的 tarball 并将其通过管道传输到构建中,以用作 上下文:
$ tar czf foo.tar.gz *
$ docker build - < foo.tar.gz
构建从 tarball 上下文解析 Dockerfile。您可以使用该标志指定 Dockerfile 的名称和位置,相对于
tarball 的根。以下命令在 tarball 中构建 using:--file
test.Dockerfile
$ docker build --file test.Dockerfile - < foo.tar.gz
远程上下文
您可以指定远程 Git 存储库、tarball 或纯文本的地址 file 作为您的构建上下文。
如果远程 tarball 是一个文本文件,则构建器不会收到任何文件系统 context,而是假设远程 file 是一个 Dockerfile。请参阅 空构建上下文。
Git 存储库
当您将指向 Git 存储库位置的 URL 作为参数传递时
到 ,生成器使用存储库作为构建上下文。docker build
构建器执行存储库的浅层克隆,仅下载 HEAD 提交,而不是整个历史记录。
构建器以递归方式克隆存储库及其包含的任何子模块。
$ docker build https://github.com/user/myrepo.git
默认情况下,构建器会在 存储库。
URL 片段
您可以将 URL 片段附加到 Git 存储库地址,以使构建器 克隆存储库的特定分支、标签和子目录。
URL 片段的格式为 ,其中:#ref:dir
ref
是分支、标签或提交哈希的名称dir
是存储库中的子目录
例如,以下命令使用分支
和该分支中的子目录作为构建上下文:container
docker
$ docker build https://github.com/user/myrepo.git#container:docker
下表显示了所有有效的后缀及其内部版本 上下文:
生成语法后缀 | 已使用的提交 | 使用的构建上下文 |
---|---|---|
myrepo.git | refs/heads/<default branch> | / |
myrepo.git#mytag | refs/tags/mytag | / |
myrepo.git#mybranch | refs/heads/mybranch | / |
myrepo.git#pull/42/head | refs/pull/42/head | / |
myrepo.git#:myfolder | refs/heads/<default branch> | /myfolder |
myrepo.git#master:myfolder | refs/heads/master | /myfolder |
myrepo.git#mytag:myfolder | refs/tags/mytag | /myfolder |
myrepo.git#mybranch:myfolder | refs/heads/mybranch | /myfolder |
当您使用提交哈希作为 URL 片段中时,请使用完整的
提交的 40 个字符的字符串 SHA-1 哈希。短哈希值,例如哈希值
truncated 为 7 个字符。ref
# ✅ The following works:
docker build github.com/docker/buildx#d4f088e689b41353d74f1a0bfcd6d7c0b213aed2
# ❌ The following doesn't work because the commit hash is truncated:
docker build github.com/docker/buildx#d4f088e
保留 .git
目录
默认情况下,BuildKit 在使用 Git 上下文时不保留目录。
你可以通过设置 BUILDKIT_CONTEXT_KEEP_GIT_DIR
build 参数来配置 BuildKit 保留目录。
如果您想在构建过程中检索 Git 信息,这可能很有用:.git
# syntax=docker/dockerfile:1
FROM alpine
WORKDIR /src
RUN --mount=target=. \
make REVISION=$(git rev-parse HEAD) build
$ docker build \
--build-arg BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
https://github.com/user/myrepo.git#main
私有仓库
当您指定同时也是私有存储库的 Git 上下文时,构建器 需要您提供必要的身份验证凭证。您可以使用 SSH 或基于令牌的身份验证。
Buildx 会自动检测并使用 SSH 凭据,如果 Git 上下文
specify 是 SSH 或 Git 地址。默认情况下,它使用 .
您可以配置要与 --ssh
标志一起使用的 SSH 凭证。$SSH_AUTH_SOCK
$ docker buildx build --ssh default git@github.com:user/private.git
如果要改用基于令牌的身份验证,则可以传递令牌
使用 --secret
标志。
$ GIT_AUTH_TOKEN=<token> docker buildx build \
--secret id=GIT_AUTH_TOKEN \
https://github.com/user/private.git
注意
不要用于机密。
--build-arg
使用 stdin 中的 Dockerfile 的远程上下文
使用以下语法使用本地 filesystem,同时使用 stdin 中的 Dockerfile。
$ docker build -f- <URL>
语法使用 -f(或 --file)选项来指定要使用的 Dockerfile,并且 它使用连字符 (-) 作为文件名,指示 Docker 从 stdin 的
这在您想要从 不包含 Dockerfile 的存储库。或者,如果您想使用 自定义 Dockerfile,而无需维护您自己的存储库分支。
以下示例使用 stdin 中的 Dockerfile 构建镜像,并将
GitHub 上 hello-world 存储库中的文件。hello.c
docker build -t myimage:latest -f- https://github.com/docker-library/hello-world.git <<EOF
FROM busybox
COPY hello.c ./
EOF
远程 tarball
如果您将 URL 传递给远程 tarball,则 URL 本身将发送到构建器。
$ docker build http://server/context.tar.gz
#1 [internal] load remote build context
#1 DONE 0.2s
#2 copy /context /
#2 DONE 0.1s
...
下载操作将在 BuildKit 守护程序
正在运行。请注意,如果您使用的是远程 Docker 上下文或远程
builder 的 build 文件,它不一定与您发布 build 的计算机相同
命令。BuildKit 获取 并将其用作构建
上下文。Tarball 上下文必须是符合标准 Unix 格式的 tar 存档,并且可以使用 、 或 (无压缩) 格式中的任何一种进行压缩。context.tar.gz
tar
xz
bzip2
gzip
identity
空上下文
当您使用文本文件作为构建上下文时,构建器会解释该文件 作为 Dockerfile 进行。使用文本文件作为上下文意味着构建没有 filesystem 上下文。
当 Dockerfile 不依赖时,您可以使用空的构建上下文进行构建 在任何本地文件上。
如何在没有上下文的情况下构建
您可以使用标准输入流传递文本文件,也可以通过指向 远程文本文件的 URL。
$ docker build - < Dockerfile
Get-Content Dockerfile | docker build -
docker build -t myimage:latest - <<EOF
FROM busybox
RUN echo "hello world"
EOF
$ docker build https://raw.githubusercontent.com/dvdksn/clockbox/main/Dockerfile
在没有文件系统上下文的情况下进行构建时,Dockerfile 指令(例如 can't refer to local files):COPY
$ ls
main.c
$ docker build -<<< $'FROM scratch\nCOPY main.c .'
[+] Building 0.0s (4/4) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 64B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 2B 0.0s
=> ERROR [1/1] COPY main.c . 0.0s
------
> [1/1] COPY main.c .:
------
Dockerfile:2
--------------------
1 | FROM scratch
2 | >>> COPY main.c .
3 |
--------------------
ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref 7ab2bb61-0c28-432e-abf5-a4c3440bc6b6::4lgfpdf54n5uqxnv9v6ymg7ih: "/main.c": not found
.dockerignore 文件
您可以使用文件从
构建上下文。.dockerignore
# .dockerignore
node_modules
bar
这有助于避免将不需要的文件和目录发送给构建器。 提高构建速度,尤其是在使用远程构建器时。
文件名和位置
当您运行构建命令时,构建客户端会查找在上下文的根目录中命名的文件。如果此文件存在,则
与文件中的模式匹配的文件和目录将从
build 上下文。.dockerignore
如果您使用多个 Dockerfile,则可以为每个 Dockerfile 使用不同的 ignore-files Dockerfile 文件。为此,请使用 ignore-files 的特殊命名约定。 将 ignore-file 放在与 Dockerfile 相同的目录中,并在 ignore-file 替换为 Dockerfile 的名称,如以下示例所示。
.
├── index.ts
├── src/
├── docker
│ ├── build.Dockerfile
│ ├── build.Dockerfile.dockerignore
│ ├── lint.Dockerfile
│ ├── lint.Dockerfile.dockerignore
│ ├── test.Dockerfile
│ └── test.Dockerfile.dockerignore
├── package.json
└── package-lock.json
如果两者都存在,则特定于 Dockerfile 的 ignore-file 优先于构建上下文根目录中的文件。.dockerignore
语法
该文件是一个以换行符分隔的模式列表,类似于
文件 globs 的 Unix shell 的 Loms 文件。ignore 模式中的前导和尾部斜杠是
忽视。以下模式都排除了 build 上下文根目录下的子目录中命名的文件或目录:.dockerignore
bar
foo
/foo/bar/
/foo/bar
foo/bar/
foo/bar
如果 file 中的一行以第 1 列开头,则此行
被视为注释,在被 CLI 解释之前被忽略。.dockerignore
#
#/this/is/a/comment
如果您有兴趣了解模式匹配逻辑的确切细节,请查看 GitHub 上的 moby/patternmatcher 存储库,其中包含源代码。.dockerignore
匹配
以下代码片段显示了一个示例文件。.dockerignore
# comment
*/temp*
*/*/temp*
temp?
此文件会导致以下生成行为:
统治 | 行为 |
---|---|
# comment | 忽视。 |
*/temp* | 排除名称以根的任何直接子目录中开头的文件和目录。例如,plain 文件被排除在外,目录 .temp /somedir/temporary.txt /somedir/temp |
*/*/temp* | 从根目录下两级的任何子目录中排除以 开头的文件和目录。例如,被排除。temp /somedir/subdir/temporary.txt |
temp? | 排除根目录中名称为 .例如,和 are excluded。temp /tempa /tempb |
匹配是使用 Go 的 filepath 完成的。匹配
函数规则。
预处理步骤使用 Go 的 filepath。清理
函数来修剪空格并删除 和 .
预处理后为空的行将被忽略。.
..
注意
由于历史原因,该模式被忽略。
.
除了 Go 的规则之外,Docker 还支持特殊的通配符
匹配任意数量的目录(包括零)的字符串。为
example,排除以 found anywhere 结尾的所有文件。
构建上下文。filepath.Match
**
**/*.go
.go
您可以使用该文件排除 和 文件。这些文件仍按原样发送给生成器
运行构建所需的。但是,您不能使用 、 或 bind 挂载将文件复制到镜像中。.dockerignore
Dockerfile
.dockerignore
ADD
COPY
否定匹配项
您可以在行前加上 (感叹号) 以例外
排除。下面是一个使用此
机制:!
.dockerignore
*.md
!README.md
上下文目录下的所有 markdown 文件,除了
从上下文中排除。请注意,子目录下的 markdown 文件是
仍然包括在内。README.md
异常规则的位置会影响行为:最后一行
匹配特定文件的 () 确定它是否为
包含或排除。请考虑以下示例:!
.dockerignore
*.md
!README*.md
README-secret.md
除了 README 文件以外的 .README-secret.md
现在考虑以下示例:
*.md
README-secret.md
!README*.md
包括所有 README 文件。中间线没有效果,因为 matches 和 comes last。!README*.md
README-secret.md