跳到主要内容

Dockerfile 语法

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。Docker 通过读取 Dockerfile 中的指令自动构建镜像。

基础结构

Dockerfile 一般分为四部分:

  1. 基础镜像信息:使用 FROM 指令。
  2. 维护者信息:使用 LABEL 指令(旧版本使用 MAINTAINER)。
  3. 镜像操作指令RUNCOPYADD 等。
  4. 容器启动时执行指令CMDENTRYPOINT

指令详解

FROM

指定基础镜像,必须是 Dockerfile 的第一条指令(ARG 除外)。

FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
  • 示例:FROM ubuntu:20.04

LABEL

给镜像添加元数据,用于替代旧的 MAINTAINER 指令。

LABEL <key>=<value> <key>=<value> ...
  • 示例:LABEL version="1.0" description="这是一个 Web 服务器"

RUN

用于执行后面跟着的命令行命令。有以下两种格式:

  1. Shell 格式
    RUN <命令行命令>
    # <命令行命令> 等同于,在终端操作的 shell 命令。
  2. Exec 格式
    RUN ["可执行文件", "参数1", "参数2"]
    # 例如:
    # RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。尽量将多条命令合并,使用 && 连接,并用 \ 换行。

COPY

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

COPY [--chown=<user>:<group>] <源路径>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
  • <目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

ADD

ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。

  • 区别
    • ADD 的源路径可以是 URL。
    • 如果源文件是一个 tar 压缩文件,ADD 会自动解压。

CMD

类似于 RUN 指令,用于指定容器启动时默认执行的命令。

CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...]
CMD ["<param1>","<param2>",...] # 该写法是为 ENTRYPOINT 指令提供默认参数

注意:如果 Dockerfile 中有多个 CMD 指令,只有最后一个生效。CMD 会被 docker run 之后的参数替换。

ENTRYPOINT

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

ENTRYPOINT ["<execute>", "<param1>", "<param2>", ...]
  • 搭配使用:可以让镜像变成像命令一样使用,或者在启动时进行一些预处理工作。

ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

ARG

构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

ARG <参数名>[=<默认值>]

WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。

WORKDIR <工作目录路径>

EXPOSE

声明端口。

EXPOSE <端口1> [<端口2>...]
  • 作用:
    1. 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
    2. 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

VOLUME

定义匿名卷。

VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
  • 作用:避免重要的数据,因容器重启而丢失,这是非常致命的。避免容器不断变大。

USER

用于指定执行后续命令的用户和用户组(用户和用户组必须提前已经存在)。

USER <用户名>[:<用户组>]

HEALTHCHECK

用于指定某个程序或者指令来监控 docker 容器服务的运行状态。

HEALTHCHECK [选项] CMD <命令>

ONBUILD

用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 A)。当有新的 Dockerfile 使用 FROM A 基于 A 镜像构建时,这时候 A 镜像 Dockerfile 里的 ONBUILD 指定的命令才会执行。

ONBUILD <其它指令>

最佳实践

  1. 精简镜像用途:尽量让每个镜像的用途都比较集中单一,避免构造大而复杂、多功能的镜像。
  2. 选用合适的基础镜像:容器的核心是应用。选择过大的父镜像(如 Ubuntu 系统镜像)会造成最终生成应用镜像的臃肿,推荐选用瘦身过的应用镜像(如 node:slim),或者较为小巧的系统镜像(如 alpinebusyboxdebian)。
  3. 减少镜像层数:尽量合并 RUN 指令,清理无用的缓存和文件。
  4. 使用 .dockerignore:忽略不需要发送给 Docker daemon 的文件。