如何包含 Docker 构建上下文之外的文件

如何包含 Docker 构建上下文之外的文件

技术背景

在使用 Docker 构建镜像时,Dockerfile 中的 ADDCOPY 命令只能访问构建上下文内的文件。构建上下文是指执行 docker build 命令时指定的目录,Docker 会将该目录及其子目录的内容发送给 Docker 守护进程。这就导致无法直接引用构建上下文之外的文件,给一些项目的构建带来了不便,尤其是不想为了适应 Docker 而重构整个项目结构的情况。

实现步骤

1. 使用 -f 指定 Dockerfile

可以独立于构建上下文指定 Dockerfile,例如:

1
docker build -f docker-files/Dockerfile .

从 Docker 18.03.0-ce 版本开始,也可以将 Dockerfile 放在构建上下文之外,如:

1
docker build -f ../Dockerfile .

2. 使用 –build-arg 传递文件内容

在 Dockerfile 中使用 ARG 定义参数,然后在构建时传递文件内容:

1
2
ARG SSH_KEY
RUN echo "$SSH_KEY" > /root/.ssh/id_rsa

构建命令如下:

1
docker build -t some-app --build-arg SSH_KEY="$(cat ~/file/outside/build/context/id_rsa)" .

但需要注意,不建议使用此方法传递敏感信息,因为构建时的变量值可以通过 docker history 命令查看。

3. 挂载目录(仅适用于 Linux)

在 Linux 上可以使用 mount --bind 命令挂载其他目录:

1
mount --bind olddir newdir

4. 使用 buildx 的 –build-context 选项

如果 Dockerfile 版本为 1.4+ 且 buildx 版本为 0.8+,可以使用以下命令:

1
docker buildx build --build-context othersource=../something/something .

然后在 Dockerfile 中使用 ADD --from=othersource 引用该上下文:

1
ADD --from=othersource . /stuff

5. 改变构建上下文

改变构建上下文目录,例如将父目录作为构建上下文:

1
docker build -t hello-demo-app ..

6. 创建 tarball

创建所需文件的 tarball 并将其作为构建上下文:

1
tar zc /dir1 /dir2 | docker build -

7. 使用 docker-compose 的 additional_contexts

docker-compose.yml 中定义多个构建上下文:

1
2
3
4
5
6
frontend:
build:
context: ./frontend
additional_contexts:
- configs=./configs
dockerfile: Dockerfile

在 Dockerfile 中引用:

1
2
3
4
FROM node:18.16.1-alpine3.17 as builder
RUN mkdir /frontend
WORKDIR /frontend
COPY --from=configs ./.env.prod .

核心代码

使用 -f 指定 Dockerfile

1
docker build -f docker-files/Dockerfile .

使用 –build-arg 传递文件内容

1
2
ARG SSH_KEY
RUN echo "$SSH_KEY" > /root/.ssh/id_rsa
1
docker build -t some-app --build-arg SSH_KEY="$(cat ~/file/outside/build/context/id_rsa)" .

使用 buildx 的 –build-context 选项

1
docker buildx build --build-context othersource=../something/something .
1
ADD --from=othersource . /stuff

最佳实践

  • 避免传递敏感信息:如使用 --build-arg 传递文件内容时,避免传递敏感信息,如私钥、用户凭证等。
  • 合理选择构建上下文:选择合适的构建上下文目录,避免将不必要的文件包含在构建上下文中,以减少构建时间和镜像大小。
  • 使用 .dockerignore 文件:使用 .dockerignore 文件排除不需要的文件和目录,进一步减少构建上下文的大小。

常见问题

1. 使用 –build-arg 传递敏感信息的安全问题

使用 --build-arg 传递敏感信息时,这些信息会在 docker history 命令中可见,存在安全风险。可以考虑使用多阶段构建或其他安全机制来处理敏感信息。

2. 改变构建上下文导致的问题

改变构建上下文可能会影响 .dockerignore 文件的作用,需要确保 .dockerignore 文件位于正确的目录中。同时,构建上下文过大可能会导致构建时间过长。

3. 使用 buildx 功能的兼容性问题

使用 buildx 的 --build-context 选项时,可能存在兼容性问题,例如在某些操作系统或版本中可能无法正常工作。需要确保 Dockerfile 和 buildx 版本符合要求。


如何包含 Docker 构建上下文之外的文件
https://119291.xyz/posts/2025-04-22.how-to-include-files-outside-of-dockers-build-context/
作者
ww
发布于
2025年4月23日
许可协议