6.2 排除文件与多阶段构建

任务一:使用 .dockerignore 排除文件
在构建Docker镜像时,我们经常会遇到这样的问题:项目目录中有很多与运行应用无关的文件(比如文档、许可证文件、测试文件等),如果全部打包到镜像中,会白白增加镜像大小。这时候 .dockerignore 就派上用场了!
.dockerignore 文件的作用类似于 .gitignore,可以指定哪些文件或目录不需要被复制到Docker镜像中。这样做的好处是:
- 减小镜像体积
- 加快构建速度
- 避免敏感信息泄露
1、创建项目目录并进入
mkdir /root/ignore
cd /root/ignore
2、执行以下命令,下载测试用的示例文件
这个脚本会在当前目录中准备三个文件,用于演示 .dockerignore 的效果。
curl -fsSL https://git.seahi.me/seahi/docker/raw/branch/main/6.1%E6%9E%84%E5%BB%BA%E9%95%9C%E5%83%8F%E5%8E%9F%E5%88%99/download_me.sh | bash

3、创建 .dockerignore 文件
vim .dockerignore
文件内容如下:
LICENSE
go/
在这个配置中:
LICENSE:排除许可证文件(运行应用不需要)go/:排除整个go目录
4、创建 Dockerfile 文件
vim Dockerfile
文件内容如下:
FROM alpine
WORKDIR /app
COPY . .
CMD ["ls","-la"]
这个简单的Dockerfile做了以下事情:
- 使用轻量的alpine基础镜像
- 设置工作目录为
/app - 复制当前目录所有文件到容器(
.dockerignore中指定的文件会被排除) - 启动容器时执行
ls -la命令,列出复制到容器的文件
5、构建镜像
docker build -t ignore .
6、运行容器查看效果
通过运行容器,我们可以看到哪些文件被实际复制到了镜像中。
docker run --rm ignore

.dockerignore 的作用!它成功地将这些不需要的文件排除在镜像之外。任务二:对比单阶段与多阶段构建
在这个任务中,我们将通过一个实际的Go应用程序,对比单阶段构建和多阶段构建的镜像大小差异。结果可能会让你大吃一惊!
多阶段构建可以将"构建阶段"和"运行阶段"分离:
- 第一阶段:使用包含完整开发工具的镜像编译应用
- 第二阶段:使用精简的基础镜像,只复制编译好的可执行文件
这样最终的镜像只包含运行所需的最小内容!
1、创建项目目录
mkdir /root/go
cd /root/go
2、创建一个简单的Go程序
vim app.go
输入以下内容:
package main
import "fmt"
func main() {
fmt.Println("Hello World!")
}
这是一个最简单的Go程序,只打印一句 “Hello World!"。虽然简单,但足以演示多阶段构建的威力。
方案一:单阶段构建(传统方式)
3、创建 Dockerfile-1(使用单阶段构建)
vim Dockerfile-1
文件内容如下:

在 Dockerfile 第2行加入以下内容:
ENV http_proxy=http://192.168.192.199:10809
ENV https_proxy=http://192.168.192.199:10809
ENV all_proxy=http://192.168.192.199:10809
最终文件内容如下:

4、构建单阶段镜像
docker build -f Dockerfile-1 -t go:v1 .

5、查看镜像大小
docker images go

单阶段构建的镜像大小是 421 MB!
一个只打印 “Hello World!” 的简单程序,镜像竟然要400多MB,这显然不合理。大部分空间都被编译工具占用了,而这些工具在程序运行时完全用不到。
这种方式的问题在于:最终的镜像将包含整个Go开发环境,包括:
- Go编译器
- Go工具链
- 各种构建工具
这些东西运行时根本用不到,却占用大量空间!
方案二:多阶段构建(优化方式)
6、创建 Dockerfile-2(使用多阶段构建)
vim Dockerfile-2
文件内容如下:

这个Dockerfile分为两个阶段:
第一阶段(builder):
- 使用
alpine镜像(安装Go编译器) - 设置工作目录
- 复制源代码
- 编译生成可执行文件
/app/app
第二阶段(最终镜像):
- 使用更小的
alpine基础镜像(不包含Go编译器) - 只从第一阶段复制编译好的可执行文件
- 设置启动命令
最终镜像中不包含Go编译器和源代码,大大减小了体积!
7、构建多阶段镜像
docker build -f Dockerfile-2 -t go:v2 .

8、对比两个镜像的大小
docker images | grep go

对比结果:
- 单阶段构建(go:v1):421 MB
- 多阶段构建(go:v2):10.5 MB
多阶段构建的镜像比单阶段构建小了 40倍!这意味着:
- 下载时间快40倍
- 节省存储空间40倍
- 启动速度更快
- 攻击面更小(不包含不必要的开发工具)
验证两种构建的运行结果一致

多阶段构建的适用场景
多阶段构建特别适合以下场景:
编译型语言项目:
- Go语言应用
- Java应用(Maven/Gradle构建)
- C/C++应用
- Rust应用
前端项目:
- React/Vue/Angular应用(需要npm build)
- TypeScript项目
通用原则: 只要你的应用需要"构建"步骤,而构建工具在运行时不需要,就应该使用多阶段构建!
总结:Docker镜像构建的黄金法则
通过本次实验,我们学习了两个重要的镜像优化技巧。在实际工作中,应该将这些技巧结合起来使用:
1. 选择合适的基础镜像
- 优先选择alpine等精简版本
- 例如:
alpine(5MB)vsubuntu(80MB+)
2. 减少镜像层数
- 合并多个RUN命令(使用
&&连接) - 清理不必要的缓存文件
3. 使用多阶段构建
- 将构建环境与运行环境分离
- 只保留运行所需的最终产物
- 特别适合编译型语言和需要构建的项目




