1. 理解 Docker Build 上下文

Docker build 上下文(Build Context)是指执行 docker build 命令时,Docker CLI 会将当前目录(或指定路径)下的所有文件和子目录打包发送给 Docker Daemon 的过程。

这个上下文的作用是:Dockerfile 中所有 COPYADD 等操作都只能访问上下文范围内的文件。也就是说,Dockerfile 所在目录之外的文件是无法被访问的,除非你显式地将其包含在构建上下文中。

✅ 构建上下文的常见来源:

  • 本地文件系统路径(如 . 表示当前目录)
  • Git 仓库地址(如 https://github.com/xxx.git

⚠️ 踩坑点:

如果你的构建目录中存在不必要的大文件(如日志、备份、压缩包等),它们都会被包含进构建上下文,导致构建过程变慢,甚至失败。


2. 构建上下文带来的问题

我们来看一个简单的 Dockerfile 示例:

FROM centos:7
MAINTAINER [email protected]
COPY jdk-8u202-linux-x64.rpm /

执行构建命令:

docker build -t javaapplication .

输出如下:

Sending build context to Docker daemon  178.4MB
...
Successfully built 9c58f775bb80

现在,我们在当前目录下新增一个 186MB 的 jdk-8u202-linux-x64.tar.gz 文件,不修改 Dockerfile,再次构建:

Sending build context to Docker daemon  372.5MB
...
Successfully built 9c58f775bb80

问题总结

  • 构建上下文自动包含了当前目录下的所有内容,包括未被使用的文件。
  • 这会导致构建上下文体积膨胀,浪费带宽、内存和时间。

3. 使用 .dockerignore 文件优化上下文

.dockerignore 文件的作用类似于 .gitignore,用于指定哪些文件或目录不应被包含在构建上下文中。

✅ 示例:

创建 .dockerignore 文件,排除 tar.gz 文件:

echo "jdk-8u202-linux-x64.tar.gz" > .dockerignore

再次执行构建:

Sending build context to Docker daemon  178.4MB

效果

  • 构建上下文大小恢复到原来的 178.4MB。
  • 有效避免了不必要的文件传输。

4. 使用 EOF 构建无上下文镜像

如果你的 Dockerfile 不涉及 COPYADD 操作,可以使用以下方式构建镜像,完全避免构建上下文

docker build -t test -<<EOF
FROM centos:7
MAINTAINER admin@example.com
RUN echo "Welcome to Bealdung"
EOF

输出如下:

Sending build context to Docker daemon  2.048kB

适用场景

  • Dockerfile 中没有使用本地文件(如 COPY、ADD)。
  • 快速测试或构建简单镜像。

⚠️ 注意

  • 一旦使用了 COPYADD,这种方式就不再适用。

5. Docker 镜像优化技巧

5.1 使用多阶段构建(Multi-Stage Builds)

多阶段构建允许你在同一个 Dockerfile 中使用多个 FROM 指令,每个阶段可以使用不同的基础镜像。最终镜像中只保留你需要的文件。

✅ 示例:

FROM centos:7 as builder
RUN yum -y install maven
COPY spring-boot-application /spring-boot-application
WORKDIR /spring-boot-application/
RUN mvn clean package -Dmaven.test.skip=true

FROM centos:7
RUN yum install -y epel-release \
    && yum install -y maven wget \
    && yum -y install java-1.8.0-openjdk \
    && yum clean all 
COPY --from=builder /spring-boot-application/target/spring-boot-application-0.0.1-SNAPSHOT.jar /
CMD ["java -jar ","-c","/spring-boot-application-0.0.1-SNAPSHOT.jar && tail -f /dev/null"]

优势

  • 构建环境与运行环境分离。
  • 镜像体积大幅减小。

5.2 合并 RUN 指令减少图层

每条 RUN 指令都会创建一个新的图层(Layer),图层数量越多,镜像体积越大。

❌ 不推荐写法:

RUN apt-get update
RUN apt-get install -y python

✅ 推荐写法:

RUN apt-get update && apt-get install -y python

效果

  • 图层数量减少。
  • 镜像体积更小。
  • 更易于维护。

5.3 自定义基础镜像

如果你有多个服务使用了相同的依赖项,建议:

  • 创建一个自定义的基础镜像,预装通用依赖。
  • 利用 Docker 的缓存机制,提升构建效率。

优势

  • 减少重复构建。
  • 提高构建速度。
  • 统一依赖版本。

6. 总结

优化方式 说明 适用场景
.dockerignore 排除不必要的文件 所有项目
EOF 构建 无需上下文,构建最小镜像 简单镜像
多阶段构建 分离构建和运行阶段 Java、Go 等编译型项目
合并 RUN 指令 减少图层数量 所有 Dockerfile
自定义基础镜像 提前安装通用依赖 多服务共享依赖

建议

  • 从构建上下文开始优化,再结合 Dockerfile 优化技巧。
  • 对于大型项目,推荐使用多阶段构建 + 自定义基础镜像组合方案。

⚠️ 避免踩坑

  • 不要忽视 .dockerignore 文件。
  • 不要频繁使用 RUN 指令。
  • 不要将大文件随意放在构建目录中。

原始标题:Reduce Build Context for Docker Build Command

« 上一篇: Kaniko 简介