关键在于让变动少的指令靠前、变动多的靠后:FROM几乎不变须置顶,接着安装系统工具、运行时和依赖(如Node.js先COPY package.json再npm install),源码和配置等高频变更内容放最后;用.dockerignore排除无关文件,并合并RUN指令以减少层数、避免隐性缓存失效。
关键在于让变动少的指令靠前,变动多的靠后。docker 构建缓存是逐层生效的,一旦某一层失效,它后面所有层都会重建。
把基础和依赖放前面
FROM 指令几乎不变,必须放在最顶上。接着是安装系统工具、语言运行时、项目依赖这些相对稳定的步骤。
- 比如 Node.js 项目,先 COPY package.json 和 package-lock.json,再 RUN npm install
- Java 项目,先 COPY pom.xml,再 RUN mvn dependency:resolve
- Python 项目,先 COPY requirements.txt,再 RUN pip install -r requirements.txt
源码和配置放最后
应用代码、模板文件、环境配置这类内容改得勤,要放到 Dockerfile 靠后位置。
- COPY . . 这类全量复制尽量放在依赖安装之后
- 如果某些配置文件变更频繁(如 config.yaml),可单独拆出来 COPY,避免牵连前面的依赖层
- 用 .dockerignore 排除日志、.git、node_modules 等无关文件,减少构建上下文干扰
避免隐性缓存破坏
有些写法看着没变,实际会悄悄让缓存失效。
- ENV 指令修改值(如 ENV VERSION=1.2.0 → 1.3.0),后续所有层缓存作废
- RUN 指令里用了变量或动态命令(如 RUN echo $(date) > stamp.txt),每次构建哈希都不同
- COPY 或 ADD 引用的文件内容变了,哪怕只改了一个空格,对应层及之后全部重建
合并与精简 RUN 指令
多个 RUN 合并成一个,既能减少层数,又能提升缓存稳定性。
- 不推荐:RUN apt-get update && apt-get install -y curl;RUN rm -rf /var/lib/apt/lists/*
- 推荐:RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
- 这样删除操作不会单独成层,也不会因某次构建漏删而残留垃圾


















