Dockerfile 编写要点:从零到生产环境的关键设计决策
很多人把 Dockerfile 看作几个命令的文件:FROM node:22、COPY . .、RUN npm install、CMD ["npm", "start"]。但每个 instruction 背后都有一个具体概念。这篇指南覆盖从基础到生产环境的完整决策链。
Dockerfile 是什么
Dockerfile 是文本文件,描述 Docker 镜像如何构建:FROM python:3.12、WORKDIR /app、COPY . .、RUN pip install -r requirements.txt、CMD ["python", "app.py"]。Docker 从上到下执行这些指令构建镜像,流程是:Dockerfile → docker build → Docker Image → docker run → Container。
核心概念问答(原文主线)
- 为什么需要 FROM:镜像继承的基座,决定系统与运行时;
- COPY vs ADD:ADD 有额外解压/URL 能力,能不用就不用,行为更隐晦;
- RUN vs CMD 不一样:RUN 在构建期执行并固化进层,CMD 是容器启动时的默认命令;
- CMD vs ENTRYPOINT:ENTRYPOINT 固定入口、CMD 提供可覆盖默认参数,生产容器常两者配合;
- ARG vs ENV:ARG 只在构建期可用,ENV 运行时也生效;密文类用 ARG 也有风险,要配合 secrets 机制;
- 为什么先
COPY package*.json ./:利用层缓存——依赖层不变就不重装,构建大幅加速; - .dockerignore 为什么重要:避免把 node_modules/.git 等打进构建上下文,加快上传、缩小镜像;
- 生产为何用 multi-stage build:编译产物与运行环境分离,最终镜像只留运行所需。
实践建议
- 先 COPY 依赖清单再 COPY 源码,最大化层缓存命中;
- 生产镜像用 multi-stage + 非 root 用户 + 精简 base(如 distroless/alpine);
- ENTRYPOINT 与 CMD 分开写:入口固定,参数可覆盖;敏感信息走构建 secrets 不进层。
来源:A Complete Guide to Writing Dockerfiles from Beginner to Production - DEV Community