一、什么是 Dockerfile¶
Dockerfile 是一个文本文件,用来定义 Docker 镜像的构建步骤。文件里的每一条指令,都会成为镜像构建过程中的一个动作,例如选择基础镜像、安装依赖、复制文件、设置环境变量以及定义容器启动命令。
它的核心价值在于:
- 把镜像制作过程代码化
- 让构建过程可复现、可审计
- 让团队能够用统一方式交付容器镜像
二、Dockerfile 应该怎么写¶
从工程实践看,编写 Dockerfile 可以按照一条很稳定的思路展开:
- 先选择合适的基础镜像
- 再准备运行环境和依赖
- 然后复制应用文件
- 最后定义容器启动方式
如果把这个流程进一步拆开,通常可以归纳为:
- 找到一个合适的基础镜像
- 按需切换系统源或安装依赖
- 创建运行用户并设置权限
- 拷贝应用和配置文件
- 指定启动命令
这条链路非常适合绝大多数业务镜像的起步阶段。
三、最常见的 Dockerfile 指令有哪些¶
Dockerfile 常用指令主要包括:
FROM:指定基础镜像LABEL:写入元数据RUN:执行构建时命令EXPOSE:声明暴露端口CMD:定义默认启动命令ENTRYPOINT:定义主启动命令ENV:设置环境变量ADD:复制文件,支持压缩包自动解压COPY:复制文件或目录WORKDIR:设置工作目录USER:设置启动用户ARG:定义构建参数
其中 MAINTAINER 虽然历史上常见,但现在已经不推荐继续使用,实际生产中更建议使用 LABEL 替代。
四、从几个典型例子理解核心指令¶
4.1 FROM:所有镜像构建的起点¶
任何 Dockerfile 几乎都从 FROM 开始,因为你需要先确定镜像建立在哪个基础环境之上。
FROM registry.cn-hangzhou.aliyuncs.com/abroad_images/centos:7
基础镜像选择会直接影响:
- 镜像体积
- 软件兼容性
- 安全补丁来源
- 后续构建复杂度
4.2 RUN:在构建阶段执行命令¶
例如创建一个运行用户:
FROM registry.cn-hangzhou.aliyuncs.com/abroad_images/centos:7
RUN useradd dot
配合 docker build -t centos:user . 构建后,就可以在容器中验证用户是否存在。
4.3 ENV:设置环境变量¶
FROM registry.cn-hangzhou.aliyuncs.com/abroad_images/centos:7
RUN useradd dot
ENV envir=test version=1.0
CMD echo "envir:$envir version:$version"
这类写法适合给容器注入默认环境变量,或为后续启动命令提供参数。
4.4 LABEL:写入镜像元数据¶
FROM registry.cn-hangzhou.aliyuncs.com/abroad_images/centos:7
LABEL maintainer="dot" version="demo"
LABEL multiple="true"
相比已废弃的 MAINTAINER,LABEL 更灵活,也更适合现代镜像治理。
五、ADD 和 COPY 到底怎么选¶
这是 Dockerfile 初学者最容易混淆的一组指令。
5.1 ADD 更适合什么场景¶
当你需要把压缩包复制到镜像里,并自动解压时,ADD 会更方便:
FROM nginx
ADD ./index.tar.gz /usr/share/nginx/html/
WORKDIR /usr/share/nginx/html
5.2 COPY 更适合什么场景¶
COPY 更纯粹,通常更适合普通文件和目录复制:
FROM nginx
WORKDIR /usr/share/nginx/html
COPY webroot/ .
这里有个很重要的细节:COPY webroot/ . 只会把 webroot 目录下的内容复制进去,不会把 webroot 这个目录本身带过去。
如果你想保留目录名,需要这样写:
COPY webroot/ /tmp/webroot
六、如何控制文件权限和运行用户¶
6.1 复制文件时直接设权限¶
Dockerfile 支持在复制时直接设置所有者和权限:
COPY --chown=user:group somefile.txt /path/to/destination/
COPY --chmod=644 someotherfile.txt /path/to/destination/
COPY --chown=user:group --chmod=755 executable.sh /path/to/destination/
这比先复制、再 RUN chmod 的方式更整洁,也能减少不必要的镜像层。
6.2 用 USER 切换启动用户¶
FROM registry.cn-hangzhou.aliyuncs.com/abroad_images/centos:7
RUN useradd -m tomcat -u 1001
USER 1001
这类写法有助于避免容器长期以 root 身份运行,更符合生产环境安全要求。
七、为什么要看 docker history¶
构建完镜像后,docker history 是一个非常值得常用的命令:
docker history centos:user
它能帮助你看清:
- 每一层是怎么产生的
- 哪一步引入了大量体积
- 哪些指令没有必要单独形成镜像层
如果你想做好镜像优化,docker history 几乎是必备工具。
八、写 Dockerfile 时最值得记住的几个原则¶
把 Day004 这一部分内容浓缩后,可以得到下面几个实用原则:
- 基础镜像先选对,再谈后面的优化
- 能用
LABEL就尽量不要再用MAINTAINER - 普通复制优先考虑
COPY - 需要自动解压时再考虑
ADD - 尽量在复制阶段直接处理权限和属主
- 非必要不要长期使用 root 用户运行容器
先把这些基础打牢,后面再学习 CMD、ENTRYPOINT、ARG、多架构构建和镜像优化时,就能更快建立完整的镜像制作思维。