Skip to content

4.2 Dockerfile 常用指令

如果需要更复杂的定制,可以在 Dockerfile 中添加更多指令,Dockerfile 常用指令如下表所示。

命令描述
FROM指定基础镜像,用于后续指令构建。
LABEL添加镜像的元数据,使用键值对的形式。
RUN创建镜像时,在镜像中要执行的命令。
CMD指定容器启动时默认要执行的命令(可以被覆盖)。如果执行 docker run 后面跟启动命令会被覆盖掉。
ENTRYPOINT设置容器创建时的主要命令(不可被覆盖)。
SHELL覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令。
EXPOSE声明容器运行时监听的特定网络端口。
ENV设置环境变量
COPY将文件或目录复制到镜像中。
ADD将文件、目录或远程 URL 复制到镜像中。
WORKDIR指定工作目录
VOLUME为容器创建挂载点或声明卷。
USER切换执行后续命令的用户和用户组,但这个用户必需首先已使用 RUN 的命令进行创建好了。
ARG定义在构建过程中传递给构建器的变量,可使用 "docker build" 命令设置。
ONBUILD当该镜像被用作另一个构建过程的基础时,添加触发器。
STOPSIGNAL设置发送给容器以退出的系统调用信号。
HEALTHCHECK定义周期性检查容器健康状态的命令。

FROM 指令:FROM 指令用于指定基础镜像,必须是 Dockerfile 的第一个指令。基础镜像可以是官方镜像如 ubuntu:20.04,也可以是用户自定义的镜像。如果不指定标签,默认使用 latest 标签。例如 FROM nginx 表示基于最新版 nginx 镜像构建。每个 Dockerfile 可以有多个 FROM 指令用于构建多阶段镜像,但最终只会保留最后一个 FROM 生成的镜像层。基础镜像的选择直接影响最终镜像的大小和安全性,通常推荐使用官方维护的最小化镜像如 alpine 版本。最后的 AS name 可以选择为新生成阶段指定名称。

  • FROM 指令格式:
dockerfile
FROM <image>[:<tag>] [AS <name>]
  • 参数说明:
    • <image>:必需,指定基础镜像名称。
    • :<tag>:可选,指定镜像版本标签。
    • AS <name>:可选,为构建阶段命名。
  • FROM 指令示例:
dockerfile
FROM nginx:1.23
FROM python:3.9-alpine
FROM ubuntu:20.04 AS builder

LABEL 指令:用于添加元数据到镜像,采用键值对格式。

  • LABEL 指令格式:
dockerfile
LABEL <key>=<value>
  • LABEL 指令示例:
dockerfile
LABEL version="1.0.1"
LABEL maintainer="admin@example.com"

RUN 指令:在镜像构建过程中执行命令,每条 RUN 指令都会创建一个新的镜像层。RUN 有两种格式:Shell 格式(RUN <command>)和 Exec 格式(RUN ["executable", "param1", "param2"])。Shell 格式默认使用 /bin/sh -c 执行,Exec 格式直接调用可执行文件。为了减少镜像层数,建议将多个命令合并到单个 RUN 指令中,用 && 连接命令,用 \ 换行。例如安装软件包时应该先更新包列表再安装,最后清理缓存。

  • RUN 指令格式:
dockerfile
# Shell 格式
RUN <command>

# Exec 格式
RUN ["executable", "param1", "param2"]
  • RUN 指令示例:
dockerfile
RUN yum -y install wget
RUN apt-get update && apt-get install -y \
    git \
    curl \
    && rm -rf /var/lib/apt/lists/*
RUN ["/bin/bash", "-c", "echo Hello, Docker!"]
RUN ["yum", "-y", "install", "wget"]

CMD 指令:指定容器启动时的默认命令,一个 Dockerfile 只能有一个有效的 CMD 指令。如果 docker run 指定了命令,CMD 会被覆盖。CMD 有三种格式:Exec 格式(推荐)、Shell 格式和作为 ENTRYPOINT 的参数。Exec 格式直接调用可执行文件,不经过 shell 处理环境变量;Shell 格式会通过 /bin/sh -c 执行。例如运行 Python 应用时可以使用 CMD ["python", "app.py"]

  • CMD 指令格式:
dockerfile
# Exec 格式(推荐)
CMD ["executable","param1","param2"]

# Shell 格式
CMD command param1 param2

# 作为 ENTRYPOINT 的参数
CMD ["param1","param2"]
  • CMD 指令示例:
dockerfile
# Shell 格式示例: 运行 Python 脚本
CMD python app.py

# Exec 格式示例: 运行 Nginx
CMD ["nginx", "-g", "daemon off;"]

# 作为 ENTRYPOINT 参数
CMD ["--port=8080"]

ENTRYPOINT 指令:用于设置容器启动时的主要命令,与 CMD 不同,它不会被 docker run 后面的命令覆盖。

  • ENTRYPOINT 指令格式:
dockerfile
# Shell 格式
ENTRYPOINT command param1 param2

# Exec 格式
ENTRYPOINT ["executable", "param1", "param2"]
  • ENTRYPOINT 指令示例:
dockerfile
# Shell 格式示例: 运行 Python 脚本
ENTRYPOINT python app.py					

# Exec 格式示例: 运行 Nginx
ENTRYPOINT ["nginx", "-g", "daemon off;"]

SHELL 指令:用于覆盖 Docker 默认的 shell 程序。默认情况下 Linux 使用 ["/bin/sh", "-c"],Windows 使用 ["cmd", "/S", "/C"]。这个指令会影响 RUN、CMD 和 ENTRYPOINT 的 shell 格式执行方式。

  • SHELL 指令格式
dockerfile
SHELL ["executable", "parameters"]
  • SHELL 指令示例:
dockerfile
# 切换为 PowerShell
SHELL ["powershell", "-command"]
# 切换回默认 shell
SHELL ["/bin/sh", "-c"]

EXPOSE 指令:声明容器运行时监听的网络端口,只是文档性质的说明,不会实际发布端口。实际端口映射需要在运行容器时通过 -p 参数设置。EXPOSE 可以指定 TCP 或 UDP 协议,默认是 TCP。例如 EXPOSE 80/tcp 表示容器会监听 80 端口。这个指令主要作用是帮助使用者理解容器提供的服务端口,同时被一些编排工具如 Docker Compose 使用。

  • EXPOSE 指令格式:
dockerfile
EXPOSE <port> [<port>/<protocol>...]
  • EXPOSE 指令示例:
dockerfile
# 声明单个端口
EXPOSE 80
# 声明多个端口
EXPOSE 80 443
# 指定协议
EXPOSE 53/udp

ENV 指令:设置环境变量,这些变量会在构建阶段和容器运行时生效。变量可以被后续的 RUN、CMD 等指令使用,也会持久化到容器中。定义的环境变量会出现在 docker inspect 的输出中,也可以在容器运行时通过 docker run --env 参数覆盖。

  • ENV 指令格式:
dockerfile
# 定义单个变量
ENV <key> <value>
# 一次性定义多个变量
ENV <key1>=<value1> <key2>=<value2>...
  • ENV 指令示例:
dockerfile
# 设置单个变量
ENV NODE_VERSION=18.15.0
# 设置多个变量
ENV NODE_VERSION=18.15.0 NODE_ENV=production

COPY 指令:将文件或目录从构建上下文复制到镜像中,源路径必须是相对路径(相对于 Dockerfile 所在目录),不能使用绝对路径或 ../ 父目录引用。目标路径可以是绝对路径或相对于 WORKDIR 的路径。COPY 会保留文件元数据(权限、时间戳),但不支持自动解压压缩包。与 ADD 指令相比,COPY 更推荐用于简单的文件复制操作,因为它的行为更可预测。例如复制项目代码到镜像的 /app 目录。

  • COPY 指令格式:
dockerfile
COPY <src>... <dest>
  • COPY 指令示例:
dockerfile
# 复制单个文件
COPY requirements.txt /app/
# 复制整个目录
COPY src /app/src
# 使用通配符复制多个文件
COPY *.sh /scripts/

ADD 指令:ADD 指令功能类似 COPY,但增加了自动解压压缩包和处理远程 URL 的能力。当源路径是本地压缩文件(如 .tar、.gz)时,ADD 会自动解压到目标路径。源路径也可以是 URL,Docker 会下载文件到镜像中。例如 ADD https://example.com/file.tar.gz /tmp 会下载并解压文件。由于 ADD 行为较复杂,官方建议优先使用 COPY,除非明确需要解压或下载功能。

  • ADD 指令格式:
dockerfile
ADD <src>... <dest>
  • ADD 指令示例:
dockerfile
# 添加本地文件
ADD app.jar /opt/app/
# 自动解压压缩包
ADD project.tar.gz /app
# 从 URL 下载文件
ADD https://example.com/data.json /data

WORKDIR 指令:设置工作目录,相当于 cd 命令的效果,如果目录不存在会自动创建。后续的 RUN、CMD、COPY 等指令都会在此目录下执行。WORKDIR 可以多次使用,路径可以是相对路径(基于前一个 WORKDIR)。例如 WORKDIR /app 后接 WORKDIR src 最终路径是 /app/src。使用 WORKDIR 可以避免在 RUN 指令中频繁使用 cd 命令,使 Dockerfile 更清晰。

  • WORKDIR 指令格式:
dockerfile
WORKDIR <path>
  • WORKDIR 指令示例:
dockerfile
WORKDIR /usr/src
WORKDIR app
RUN pwd  # 输出 /usr/src/app

VOLUME 指令:创建挂载点或声明卷,会在容器运行时自动挂载匿名卷。主要用途是保留重要数据(如数据库文件)或共享目录。例如 VOLUME /data 确保 /data 目录的数据持久化。实际挂载的主机目录可以通过 docker inspect 查看。VOLUME 指令不能在构建阶段向挂载点写入数据,因为这些数据在运行时会被覆盖。数据卷可以在容器间共享和重用,即使容器被删除,卷数据仍然存在。VOLUME 声明后,运行时可以通过 -v 参数覆盖,但无法在构建阶段向挂载点写入数据(会被运行时覆盖)。

  • VOLUME 指令格式:
dockerfile
VOLUME ["<path1>", "<path2>", ...]
  • VOLUME 指令示例:
dockerfile
# 声明单个卷
VOLUME /data
# 声明多个卷
VOLUME ["/data", "/config"]

USER 指令:切换执行后续指令的用户身份,用户必须已通过 RUN 指令创建。例如 USER nobody 让后续命令以 nobody 身份运行,增强安全性。该用户需要有足够的权限访问所需文件。USER 会影响 RUN、CMD、ENTRYPOINT 的执行身份。在运行时可以通过 docker run -u 覆盖此设置。典型的用法是在安装软件包后创建非 root 用户并切换,避免容器以 root 权限运行。

  • USER 指令格式:
dockerfile
USER <user>[:<group>]
  • USER 指令示例:
dockerfile
RUN groupadd -r app && useradd -r -g app appuser
USER appuser
CMD ["python", "app.py"]

ARG 指令:指令定义构建时的变量。这些变量只在构建阶段有效,不会保留到容器运行时。可以通过 docker build --build-arg <name>=<value> 覆盖默认值。例如 ARG VERSION=latest 定义版本变量。ARG 变量可以用于控制构建流程,如选择不同的软件版本。常见的预定义变量包括 HTTP_PROXY 等代理设置。

  • ARG 指令格式:
dockerfile
ARG <name>[=<默认值>]
  • ARG 指令示例:
dockerfile
ARG NODE_VERSION=14
FROM node:${NODE_VERSION}

ONBUILD 指令:设置触发器。当当前镜像被用作其他镜像的基础时,这些指令会被触发执行。例如 ONBUILD COPY . /app 会在子镜像构建时自动复制文件。ONBUILD 常用于创建基础镜像模板,子镜像可以继承特定的构建步骤。通过 docker inspect 可以查看镜像的 ONBUILD 触发器。

  • ONBUILD 指令格式:
dockerfile
ONBUILD <其他指令>
  • ONBUILD 指令示例:
dockerfile
ONBUILD RUN npm install
ONBUILD COPY . /app

STOPSIGNAL 指令:设置容器停止时发送的系统信号。信号可以是数字(如 9)或信号名(如 SIGKILL)。默认的信号是 SIGTERM,允许容器优雅退出。如果需要强制终止,可以设置为 SIGKILL。例如 STOPSIGNAL SIGTERM 确保容器收到终止信号。这个设置会影响 docker stop 命令的行为。

  • STOPSIGNAL 指令格式:
dockerfile
STOPSIGNAL <信号>
  • STOPSIGNAL 指令示例:
dockerfile
STOPSIGNAL SIGQUIT

HEALTHCHECK 指令:定义容器健康检查,Docker 会定期执行检查命令判断容器是否健康。检查命令返回 0 表示健康,1 表示不健康。选项包括 --interval(检查间隔)、--timeout(超时时间)、--start-period(启动宽限期)和 --retries(重试次数)。例如 HEALTHCHECK --interval=30s CMD curl -f http://localhost/ 每30秒检查Web服务是否响应。健康状态可以通过 docker ps 查看。

  • HEALTHCHECK 指令格式:
dockerfile
HEALTHCHECK [OPTIONS] CMD <command>
  • HEALTHCHECK 指令示例:
dockerfile
HEALTHCHECK --interval=5m --timeout=3s \
  CMD curl -f http://localhost/ || exit 1