Dockerfile 是什么
Dockerfile 是构建镜像的声明式脚本,构建命令按顺序执行其中的指令:可执行类指令(运行命令、复制文件)产出文件系统层,配置类指令(环境变量、暴露端口、启动命令)只写入镜像元数据。同一份描述配同一个上下文,重复构建的结果应当一致可复现。
基本信息
| 默认文件名 | Dockerfile,没有扩展名,放在上下文根目录 |
|---|---|
| 构建入口 | docker build -t 名称:标签 上下文路径 |
| 生成层的指令 | FROM、RUN、COPY、ADD 等 |
| 写入配置的指令 | ENV、EXPOSE、LABEL、WORKDIR、CMD、ENTRYPOINT、USER |
| 注释与换行 | 以井号开头的行为注释,长指令可用反斜杠换行 |
典型使用场景
- 把应用打包成可部署镜像:固定运行环境、依赖版本与启动方式
- 统一团队开发环境:本地与流水线用同一份构建描述,减少环境差异
- 做多阶段构建:编译阶段与运行阶段分离,最终镜像只带运行需要的文件
- 给已有镜像做定制:以官方镜像为基础,追加配置、插件与目录结构
- 把构建过程版本化:描述进版本库,改动可评审、可回溯
最小可用结构
最小可用结构
FROM node:22-alpine # 基础镜像与版本
WORKDIR /app # 设定后续指令的工作目录
COPY package.json ./ # 先复制依赖清单,便于利用层缓存
RUN npm ci --omit=dev # 安装生产依赖
COPY . . # 再复制源码
ENV NODE_ENV=production # 运行期环境变量
EXPOSE 3000 # 声明监听端口,仅作文档说明
CMD ["node", "server.js"] # 默认启动命令指令分类速查
| 指令 | 作用 | 是否生成层 |
|---|---|---|
| FROM | 指定基础镜像并开启一个构建阶段 | 否 |
| RUN | 构建期执行命令 | 是 |
| COPY 与 ADD | 从上下文或镜像复制文件 | 是 |
| WORKDIR | 设定工作目录,后续指令与启动进程都受影响 | 否 |
| ENV 与 ARG | 运行期环境变量与构建期参数 | 否 |
| EXPOSE | 声明端口,供使用者和工具参考 | 否 |
| CMD 与 ENTRYPOINT | 启动命令与入口点 | 否 |
| USER | 指定后续指令与启动进程的身份 | 否 |
动笔前想清楚的四件事
- 基础镜像选型:体积、运行时版本、是否有长期维护的分支
- 指令顺序:变更频率低的放前面,让缓存尽量命中
- 文件边界:哪些文件属于构建上下文,哪些应该排除在传输之外
- 运行身份与权限:以什么用户运行、需要写哪些目录、如何避免以特权身份跑服务
构建上下文是构建命令最后那个路径,不是 Dockerfile 所在目录。复制指令只能引用上下文里的文件,跳出上下文的路径会直接构建失败。
配置类指令几乎不增加体积,但对运行行为影响很大;改动启动命令、工作目录或用户时,要一并确认依赖路径与文件属主是否还成立。
常见失败与对应位置
- 基础镜像拉不下来:网络与镜像加速配置问题,与 Dockerfile 内容无关
- 复制文件找不到:上下文路径不对,或被排除规则挡住,报错会直接指出源文件
- 运行命令返回非零:该指令在构建环境里执行失败,先手动执行一次看真实报错
- 启动时找不到命令:产物路径与启动命令不一致,或工作目录被改动
- 运行时报权限错误:启动用户没有目标目录的写权限,需要在构建期调整属主
构建描述与运行参数是两层东西:镜像决定环境与默认启动方式,端口、挂载、变量在起容器时给。排查时先分清该改哪一层,能省下大量反复构建的时间。