镜像分层原理
镜像(Image)由一组只读层(Layer)叠加而成。每一条 Dockerfile 指令通常生成一个新层。容器启动时,Docker 在镜像层之上再加一个可写层。 分层带来两个核心优势:- 层复用:多个镜像如果基于同一个基础镜像,相同的层在本地只存一份。拉取镜像时已有的层不会重复下载。
- 写时复制 Copy-on-Write:容器修改文件时,先把文件从只读层复制到可写层再修改。镜像本身永远不变。
Dockerfile 逐指令讲解
Dockerfile 是定义镜像构建过程的文本文件。常用指令如下:官方推荐优先使用
COPY 而不是 ADD。ADD 的自动解压行为不直观,容易踩坑。CMD 与 ENTRYPOINT 的区别
两者可以组合使用:
ENTRYPOINT 定命令,CMD 定默认参数。
完整 Dockerfile 示例
下面是一个 Node.js 应用的 Dockerfile:构建与发布
1
构建镜像
在 Dockerfile 所在目录执行:
-t 指定镜像名称和标签,末尾的点表示构建上下文是当前目录。2
打标签
推送前需要给镜像加上仓库前缀:
3
推送到镜像仓库
docker login 登录。多阶段构建
编译型语言(如 Go)只需要编译产物,不需要编译环境。多阶段构建把编译和运行拆到两个阶段:构建缓存与 .dockerignore
Docker 按指令逐层缓存。某一层变化后,其后的所有层都会重新构建。.dockerignore 文件用于排除不需要进入构建上下文的文件,作用类似 .gitignore:
镜像瘦身最佳实践
- 使用
alpine或distroless等精简基础镜像 - 合并相邻的
RUN指令,减少层数 - 同一个
RUN中安装完立即清理缓存,例如apt-get clean - 不安装编辑器、
curl等调试用工具,生产镜像用不上 - 用
.dockerignore排除无关文件 - 编译型语言一律使用多阶段构建
- 固定基础镜像版本,不要直接使用
latest
延伸阅读
- Docker 基础:镜像、容器、仓库的概念回顾
- Docker 容器:镜像运行起来之后的管理
- Docker 存储:容器数据的持久化方案
- Docker 生产实践:镜像在 CI/CD 中的落地
- Kubernetes 工作负载:镜像如何被编排运行