Dockerfile 单阶段构建¶
概述¶
Docker V17.05 之前,Dockerfile 中只能有一个 FROM 指令,称为单阶段构建。
单阶段构建是指整个镜像构建过程在一个 FROM 指令中完成,所有操作(安装依赖、编译代码、配置环境等)都在同一个镜像层中进行。
实战演示¶
使用 alpine:3.22.1 做练习¶
1. 创建 Dockerfile 目录¶
2. 准备 Dockerfile 文件之前¶
可以基于基础镜像,挨个执行一下需求:
这样做的好处:
- 验证命令是否正确
- 了解依赖关系
- 减少构建失败次数
3. 准备 Dockerfile 文件¶
| Bash | |
|---|---|
Dockerfile 逐行解析¶
FROM alpine:3.22.1
指定基础镜像为 Alpine Linux 3.22.1 版本。
Alpine Linux 是一个轻量级的 Linux 发行版,适合构建小型镜像。
LABEL auth="chaic" version="1.0"
添加镜像的元数据标签:
auth:作者信息version:版本号
RUN 配置软件源
| Docker | |
|---|---|
- 替换 Alpine 的软件源为阿里云镜像
- 更新软件包索引
- 安装 vim 编辑器
使用 \ 反斜杠将多个命令合并为一行,减少镜像层数。
ENV base_dir="/data"
设置环境变量 base_dir 为 /data。
环境变量可以在后续指令中引用,如 ${base_dir}。
WORKDIR 指令
| Docker | |
|---|---|
创建工作目录 /data/image,并切换到该目录。
后续的 ADD、COPY 等指令将在该目录下执行。
ADD 指令
| Docker | |
|---|---|
- 从远程 URL 下载图片文件
- 添加 Redis 源码压缩包(ADD 会自动解压)
- 复制 Redis 源码压缩包(COPY 不解压)
COPY 6379.conf .
复制本地配置文件到容器内。
VOLUME /data
声明数据卷 /data。
数据卷用于持久化数据,容器删除后数据不会丢失。
ENTRYPOINT 和 CMD
ENTRYPOINT设置入口点命令为lsCMD提供默认参数/data- 容器启动时实际执行:
ls /data
使用 ENTRYPOINT + CMD 的组合方式,使得容器启动时可以覆盖参数但保持命令不变。
例如:
EXPOSE 8088
声明容器监听 8088 端口。
这只是文档说明,实际端口映射需要在 docker run 时使用 -p 参数。
4. 打包镜像¶
| Bash | |
|---|---|
5. 测试¶
| Bash | |
|---|---|
预期输出:列出 /data 目录的内容。
单阶段构建的特点¶
优点¶
- 简单直观
- 所有操作在一个文件中完成
- 易于理解和维护
- 构建速度快
- 不需要多阶段的复制和清理操作
- 适合小型项目
缺点¶
- 镜像体积大
- 构建工具(编译器、依赖包)会保留在最终镜像中
- 例如:如果需要编译 Go 应用,gcc 会留在镜像中
- 安全性较低
- 构建过程中的临时文件可能包含敏感信息
- 源代码可能被包含在最终镜像中
- 不够灵活
- 无法单独构建某个阶段
- 无法复用中间产物
适用场景¶
单阶段构建适合以下情况:
- 简单应用
- 直接打包运行时环境
- 不需要编译过程
- 原型开发
- 快速迭代测试
- 对镜像体积不敏感
- 小型项目
- 依赖简单
- 构建工具体积小
优化建议¶
即使使用单阶段构建,也可以采取一些优化措施:
1. 合并 RUN 指令¶
| Docker | |
|---|---|
2. 使用 .dockerignore¶
避免不必要的文件被复制到构建上下文中。
3. 清理缓存¶
4. 选用更小的基础镜像¶
与多阶段构建的对比¶
| 特性 | 单阶段构建 | 多阶段构建 |
|---|---|---|
| 复杂度 | 简单 | 复杂 |
| 镜像体积 | 较大 | 较小 |
| 安全性 | 较低 | 较高 |
| 构建时间 | 较短 | 较长 |
| 适用场景 | 简单应用 | 复杂应用 |
总结¶
单阶段构建是 Docker 镜像构建的基础方式,适合简单的应用场景。随着项目复杂度增加和对镜像体积、安全性要求的提高,建议采用多阶段构建来优化镜像。
本示例通过一个完整的 Dockerfile 演示了单阶段构建的各个环节,包括: - 基础镜像选择 - 环境配置 - 文件复制和下载 - 入口点和命令设置 - 端口和数据卷声明
理解单阶段构建有助于掌握 Docker 镜像构建的基本原理。