在运维工作中,Dockerfile 是构建 Docker 镜像的核心文件,通过一系列指令定义镜像的构建步骤和运行时配置。以下是 Dockerfile 中 20+ 常见指令的分类详解,结合示例说明其用途、注意事项及最佳实践:
一、基础镜像与维护者信息
1. FROM
作用:指定基础镜像,是 Dockerfile 的首个必需指令。
语法:
FROM <image>[:<tag>] [AS <name>] # tag 默认为 latest
示例:
FROM python:3.9-slim # 使用官方 Python 3.9 轻量镜像
FROM ubuntu:20.04 AS builder # 定义构建阶段别名(用于多阶段构建)
注意:
- 尽量使用官方镜像或经过验证的基础镜像(如 Alpine 镜像体积更小);
- 避免使用
latest
标签,确保版本确定性。
2. LABEL
作用:为镜像添加元数据(如作者、版本、描述等),便于管理。
语法:
LABEL <key>=<value> <key>=<value> ...
示例:
LABEL maintainer="doubao@example.com"
LABEL version="1.0.0" description="My web application"
注意:
- 推荐使用单个
LABEL
指令减少镜像层数; - 元数据可通过
docker inspect
查看。
二、文件操作指令
3. COPY
作用:从宿主机复制文件/目录到镜像中。
语法:
COPY [--chown=<user>:<group>] <源路径>... <目标路径>
示例:
COPY requirements.txt /app/ # 复制单个文件
COPY src/ /app/src/ # 复制目录(递归)
COPY --chown=www-data:www-data index.html /var/www/html/ # 指定文件所有者
注意:
- 源路径必须在构建上下文(
docker build
命令的路径参数)内; - 目标路径若不存在会自动创建。
4. ADD
作用:类似 COPY
,但支持远程 URL 和自动解压 tar 文件。
语法:
ADD [--chown=<user>:<group>] <源路径>... <目标路径>
示例:
ADD https://example.com/app.tar.gz /app/ # 下载并解压远程文件
ADD package.tar.xz /opt/ # 自动解压 tar 文件
注意:
- 优先使用
COPY
(语义更明确,仅复制文件); - 避免使用
ADD
处理远程 URL(可能导致缓存失效)。
5. VOLUME
作用:定义容器运行时的挂载点,用于持久化数据。
语法:
VOLUME ["/data"] # 支持单个路径或多个路径
示例:
VOLUME /var/lib/mysql # 持久化 MySQL 数据目录
注意:
- 数据卷内容不会打包到镜像中;
- 推荐在
docker run
时通过-v
或--mount
显式挂载。
三、环境配置指令
6. ENV
作用:设置环境变量,可在后续指令或运行时使用。
语法:
ENV <key>=<value> ... # 推荐用此格式(单行多变量)
ENV <key> <value> # 不推荐(可能导致空格解析问题)
示例:
ENV APP_ENV=production \DB_HOST=localhost \DB_USER=root
注意:
- 环境变量会持久化到镜像中,可通过
docker inspect
查看; - 可被
docker run -e
覆盖。
7. ARG
作用:定义构建时参数,用于传递构建过程中的变量(如版本号)。
语法:
ARG <name>[=<default value>]
示例:
ARG VERSION=1.0.0
RUN echo "Building version $VERSION"
使用方式:
docker build --build-arg VERSION=2.0.0 . # 构建时传递参数
注意:
ARG
定义的变量仅在构建时有效,运行时不可用;- 若未提供默认值且未在构建时传递,则会报错。
四、执行命令指令
8. RUN
作用:在构建时执行命令(如安装软件、编译代码等),生成新的镜像层。
语法:
RUN <command> # shell 格式(通过 /bin/sh -c 执行)
RUN ["executable", "param1", "param2"] # exec 格式(更推荐,避免 shell 处理)
示例:
RUN apt-get update && apt-get install -y python3-pip # shell 格式
RUN ["pip3", "install", "requests"] # exec 格式
注意:
- 合并多行命令(如
&&
连接)减少镜像层数; - 清理缓存文件(如
apt-get clean
)降低镜像体积。
9. CMD
作用:指定容器启动时默认执行的命令。
语法:
CMD ["executable", "param1", "param2"] # exec 格式(推荐)
CMD ["param1", "param2"] # 为 ENTRYPOINT 提供默认参数
CMD command param1 param2 # shell 格式(不推荐,可能导致信号处理问题)
示例:
CMD ["python3", "app.py"] # 容器启动时执行 python3 app.py
注意:
- 一个 Dockerfile 只能有一个
CMD
,多个则最后一个生效; - 可被
docker run
后的命令覆盖(如docker run myimage bash
)。
10. ENTRYPOINT
作用:配置容器启动时执行的命令,不可被 docker run
后的命令覆盖(但参数可追加)。
语法:
ENTRYPOINT ["executable", "param1", "param2"] # exec 格式(推荐)
ENTRYPOINT command param1 param2 # shell 格式(不推荐)
示例:
ENTRYPOINT ["python3", "app.py"] # 固定执行 python3 app.py
CMD ["--port", "8080"] # 为 ENTRYPOINT 提供默认参数
使用方式:
docker run myimage --port 8000 # 覆盖默认参数,执行 python3 app.py --port 8000
注意:
ENTRYPOINT
与CMD
常配合使用(ENTRYPOINT
定义命令,CMD
提供默认参数);- 推荐使用 exec 格式避免 shell 处理。
五、网络与端口配置
11. EXPOSE
作用:声明容器运行时监听的端口(仅作文档用途,不实际映射端口)。
语法:
EXPOSE <port> [<port>/<protocol>]
示例:
EXPOSE 80/tcp # 声明 HTTP 服务监听 80 端口
EXPOSE 53/udp # 声明 DNS 服务监听 53 UDP 端口
注意:
- 实际端口映射需在
docker run
时通过-p
或-P
实现; - 支持同时声明多个端口(如
EXPOSE 80 443
)。
六、用户与工作目录
12. WORKDIR
作用:设置后续命令的工作目录(若不存在则创建)。
语法:
WORKDIR /path/to/workdir
示例:
WORKDIR /app
COPY . . # 相当于复制到 /app/
RUN pip install -r requirements.txt
CMD ["python", "app.py"] # 工作目录为 /app
注意:
- 推荐使用绝对路径;
- 可在单个 Dockerfile 中多次使用,影响后续命令。
13. USER
作用:指定运行容器时的用户名或 UID(需先创建用户)。
语法:
USER <user>[:<group>] # 或 <UID>[:<GID>]
示例:
RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser
CMD ["python", "app.py"] # 以 appuser 身份运行
注意:
- 避免使用
root
用户运行容器(安全风险); USER
仅影响后续的RUN
、CMD
、ENTRYPOINT
指令。
七、多阶段构建(高级特性)
14. FROM ... AS <name>
作用:定义构建阶段,可在一个 Dockerfile 中使用多个 FROM
创建中间镜像,最终镜像仅包含所需层。
示例:
# 构建阶段:编译应用
FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp# 运行阶段:仅包含运行时依赖
FROM alpine:3.14
WORKDIR /app
COPY --from=builder /app/myapp . # 从 builder 阶段复制二进制文件
CMD ["./myapp"]
优势:
- 大幅减小最终镜像体积(无需包含编译工具);
- 无需在宿主机安装编译环境。
八、其他指令
15. HEALTHCHECK
作用:配置容器健康检查命令,用于监控容器状态。
语法:
HEALTHCHECK [选项] CMD <command> # 检查容器健康状态的命令
HEALTHCHECK NONE # 禁用基础镜像中的健康检查
示例:
HEALTHCHECK --interval=30s --timeout=5s \CMD curl -f http://localhost/ || exit 1
选项说明:
--interval
:检查间隔(默认 30s);--timeout
:超时时间(默认 30s);--retries
:连续失败多少次后标记为不健康(默认 3 次)。
16. STOPSIGNAL
作用:指定停止容器时发送的系统信号(如 SIGTERM
、SIGKILL
)。
语法:
STOPSIGNAL signal
示例:
STOPSIGNAL SIGINT # 相当于 Ctrl+C
17. ONBUILD
作用:定义当该镜像被用作其他镜像的基础镜像时,自动执行的命令。
语法:
ONBUILD <INSTRUCTION>
示例:
ONBUILD COPY . /app # 当此镜像被继承时,自动复制当前目录到 /app
ONBUILD RUN npm install # 自动安装依赖
注意:
ONBUILD
指令不会在当前镜像构建时执行,而是在继承该镜像的子镜像构建时执行;- 谨慎使用,可能导致意外行为。
九、最佳实践建议
-
减少镜像层数:
- 合并
RUN
命令(如apt-get update && apt-get install -y ... && rm -rf /var/lib/apt/lists/*
); - 使用多阶段构建分离编译环境与运行环境。
- 合并
-
合理使用缓存:
- 不变的内容(如依赖安装)放在 Dockerfile 前面;
- 频繁变更的内容(如源代码)放在后面。
-
安全优化:
- 避免使用
root
用户运行容器; - 最小化镜像权限(如删除不必要的工具)。
- 避免使用
-
体积优化:
- 使用轻量级基础镜像(如 Alpine、Distroless);
- 清理构建过程中的临时文件和缓存。
十、常见指令对比表
指令 | 执行时机 | 是否生成镜像层 | 能否多次使用 | 用途 |
---|---|---|---|---|
RUN |
构建时 | 是 | 是 | 执行命令(如安装软件) |
CMD |
运行时 | 否 | 否(仅最后一个生效) | 指定默认命令 |
ENTRYPOINT |
运行时 | 否 | 否(仅最后一个生效) | 配置容器启动命令 |
COPY |
构建时 | 是 | 是 | 复制文件/目录 |
ADD |
构建时 | 是 | 是 | 复制文件/目录(支持 URL 和解压) |
ENV |
构建时 | 是 | 是 | 设置环境变量 |
WORKDIR |
构建时 | 否 | 是 | 设置工作目录 |
通过合理组合这些指令,可构建出高效、安全、可维护的 Docker 镜像。建议结合官方文档(https://docs.docker.com/engine/reference/builder/)深入学习各指令细节。