docker build是推荐的镜像构建方式,基于Dockerfile实现可复现、可追溯、自动化构建;docker commit仅适用于临时调试,无法保证一致性与可维护性。

docker build 是制作自定义镜像的唯一推荐方式,docker commit 仅适用于临时调试,不能用于可复现、可交付的镜像构建。
FROM 必须是第一行,且基础镜像选错会导致后续全崩
所有 Dockerfile 必须以 FROM 开头,否则构建直接报错:FROM requires either one or three arguments。它不是“建议”,而是硬性语法要求。
-
FROM node:18-alpine比FROM node:18更轻量,体积通常小 70%,但注意:alpine 使用musl libc,某些二进制依赖(如某些 Python C 扩展、ffmpeg 静态链接库)可能不兼容 - 避免用
FROM ubuntu:latest或FROM centos:latest——latest标签不可控,今天构建成功,下周可能因基础镜像变更而失败 - 多阶段构建中可用
FROM golang:1.23 AS builder命名阶段,后续用COPY --from=builder提取产物,大幅减小最终镜像体积
COPY 和 ADD 别混用,90% 的误用都出在这儿
COPY 是复制文件的“安全默认项”,ADD 是带副作用的增强版 —— 它会自动解压 .tar.gz、.bz2 等归档,还会从 URL 下载远程资源。这种隐式行为容易引发构建失败或安全风险。
- 本地文件复制一律用
COPY ./src /app/src;需要解压?先在宿主机解好再COPY -
ADD https://example.com/app.tar.gz /tmp/看似方便,但网络波动、URL 失效、无校验机制会让构建不可靠;应改用RUN curl -fsSL ... | tar -xzf - -C /tmp并加--fail和sha256sum校验 -
COPY支持--chown(如COPY --chown=node:node . /app),ADD不支持,权限控制更受限
RUN 指令要合并,否则镜像层爆炸且体积失控
每条 RUN 指令都会生成一个新镜像层,哪怕只是 RUN apt-get update 和 RUN apt-get install -y curl 分开写,也会留下中间缓存层和未清理的 /var/lib/apt/lists。
- 正确写法:
RUN apt-get update && apt-get install -y curl nginx && rm -rf /var/lib/apt/lists/* - 用
\换行时,反斜杠后不能有空格,否则 shell 解析失败;建议用&&连接,语义清晰且天然短路 - 安装编译型语言(如 Go、Rust)时,务必在多阶段构建中分离构建环境与运行环境,否则
/usr/local/go、cargo等工具会留在最终镜像里,徒增几十 MB
CMD 和 ENTRYPOINT 的组合决定容器怎么“启动”
CMD 提供默认执行命令,可被 docker run 后的参数覆盖;ENTRYPOINT 设定容器入口,让镜像表现得更像一个可执行程序。两者混用时,ENTRYPOINT 是“主程序”,CMD 是“默认参数”。
- Web 服务推荐:
ENTRYPOINT ["node", "index.js"],不写CMD;若需传参,用docker run node-app --port 3001,--port 3001会追加到ENTRYPOINT后 - 避免
CMD ["npm", "start"]单独存在 —— 它等价于/bin/sh -c "npm start",多一层 shell,且无法接收信号(如 SIGTERM),导致优雅退出失效 - 如果必须用 shell 启动逻辑(比如检查环境变量再决定执行哪个脚本),显式写成:
ENTRYPOINT ["/bin/sh", "-c", "exec \"$1\" \"$@\"", "_"],然后CMD ["node", "index.js"]
构建上下文路径(即 docker build 命令末尾的 .)常被忽略:它把当前目录全部打包上传给 Docker daemon,哪怕你只 COPY package.json,整个 node_modules、.git、dist 也会被扫描并拖慢构建。实际项目中,务必配 .dockerignore 文件,内容至少包括:node_modules、.git、npm-debug.log、README.md。











