格式

  • 指令 参数
  • Dockerfile 无视大小写,但是代码规范中要求指令名大写,参数小写
  • Dockerfile是按顺序执行的
  • Dockerfile中第一个有效指令必须为 From,用来指定基础镜像

常用指令

FROM

FROM 指令是最为重要的一个,并且必须为 Dockerfile 文件开篇的第一个非注释行,用于为镜像文件构建过程指定基础镜像,后续的指令运行于此基础镜像提供的运行环境

这个镜像可以是任何可用镜像,默认情况下 docker build 会从本地仓库找指定的镜像文件,如果不存在就会从 Docker Hub 上拉取

语法:

1
2
3
4
# 不指定版本的情况下默认为 latest
FROM <image>
FROM <imgae>:<tag>
FROM <image>@<digest>

MAINTAINER(弃用)

Dockerfile 的制作者提供的本人详细信息

Dockerfile 不限制 MAINTAINER 出现的位置,但是推荐放到 FROM 指令之后

语法:

1
MAINTAINER <name>

name 可以是任何文本信息,一般用作者名称或者邮箱

LABEL

给镜像指定各种元数据

语法

1
LABEL <key>=<value> <key>=<value> <key>=<value> ...

一个 Dockerfile 可以写多个 LABEL,但是不推荐这么做,Dockerfile 每一条指令都会生成一层镜像,如果 LABEL 太长可以使用 \ 符号换行。构建的镜像会继承基础镜像的 LABEL,并且会去掉重复的,但如果值不同,则后面的值会覆盖前面的值

COPY

用于从宿主机复制文件到创建的新镜像文件

语法:

1
2
3
4
COPY <src>...<dest>
COPY ["<src>",..."<dest>"]
# <src>: 要复制的源文件或者目录,可以使用通配符
# <dest>: 目标路径,即正在创建的image的文件系统路径;建议<dest>使用绝对路径,否则COPY指令则以WORKDIR为起始路径

ADD

基本用法和COPY一样,ADD支持使用 TAR 文件和 URL 路径

语法:

1
2
ADD <src>...<dest>
ADD ["<src>",..."<dest>"]

规则:

  • 和 COPY 规则相同
  • 如果 <src> 为URL 并且 <dest> 没有以 / 结尾,则 <src> 指定的文件将被下载到 <dest>
  • 如果 <src> 是一个本地系统上压缩格式的 tar 文件,它会展开成一个目录;但是通过 URL 获取的 tar 文件不会自动展开
  • 如果 <src> 有多个,直接或间接使用了通配符指定多个资源,则 <dest> 必须是目录并且以 / 结尾

WORKDIR

用于为 Dockerfile 中所有的 RUN、CMD、ENTRYPOINT、COPY 和 ADD 指定设定工作目录,只会影响当前 WORKDIR 之后的指令

语法:

1
WORKDIR <dirpath>

在 Dockerfile 文件中,WORKDIR 可以出现多次,路径可以是相对路径,但是它是相对于前一个 WORKDIR 指令指定的路径

另外,WORKDIR 可以是 ENV 指定定义的变量

ENTRYPOINT

类似于 CMD 指令功能,用于给容器指定默认运行程序

语法:

1
2
ENTRYPOINT <command>
ENTRYPOINT ["<executable>", "<param1>", "<param2>"]

和 CMD 不同的是 ENTRYPOINT 启动的程序不会被 docker run 命令指定的参数所覆盖,而且,这些命令行参数会被当做参数传递给 ENTRYPOINT 指定的程序(但是,docker run 命令的 --entrypoint 参数可以覆盖 ENTRYPOINT)

docker run 命令传入的参数会覆盖 CMD 指令的内容并且附加到 ENTRYPOINT 命令最后作为其参数使用

同样,Dockerfile 中可以存在多个 ENTRYPOINT 指令,但是只有最后一个会生效

Dockerfile 中如果既有 CMD 又有 ENTRYPOINT,并且 CMD 是一个完整可执行命令,那么谁在最后谁生效

ENV

用来给镜像定义所需要的环境变量,并且可以被 Dockerfile 文件中位于其后的其他指令(如 ENVADDCOPY等)所调用,调用格式:$variable_name 或者 ${variable_naem}

语法:

1
2
ENV <key> <value>
ENV <key>=<value>...

第一种格式中,<key> 之后的所有内容都会被视为 <value> 的组成部分,所以一次只能设置一个变量

第二种格式可以一次设置多个变量,如果 <value> 当中有空格可以使用 \ 进行转义或者对 <value> 加引号进行标识;另外 \ 也可以用来续行

ARG

用法同 ENV

语法:

1
ARG <name> [=<default value>]

指定一个变量,可以在 docker build 创建镜像的时候,使用 --build-arg <varname>=<value> 来指定参数

常见问题

# COPY 与 ADD 命令的异同

1、COPY 和 ADD 命令不能拷贝上下文之外的本地文件

对于 COPY 和 ADD 命令来说,如果要把本地的文件拷贝到镜像中,那么本地的文件必须是在上下文目录中的文件。因为在执行 build 命令时,docker 客户端会把上下文中所有文件发给 docker daemon。考虑 docker 客户端和 docker daemon 不在同一台机器上的情况,build 命令只能从上下文中获取文件。如果在 Dockerfile 的 COPY 和 ADD 命令中引用了上下文中没有的文件,则会报错。

2、可以认为 ADD 是 COPY 的加强版

ADD 命令支持将远程 URL 的资源加入到镜像的文件系统

当要读取 URL 远程资源的时候,并不推荐使用 ADD 指令,而是推荐使用 RUN 指令,在 RUN 指令中执行 wgetcurl 命令。

注意:

  • 对于从远程 URL 获取资源的情况,由于 ADD 指令不支持认证,如果从远程获取资源需要认证,则只能使用 RUN wgetRUN curl 替代。
  • 如果源路径的资源发生变化,则该 ADD 指令将使 Docker Cache 失效,Dockerfile 中后续的所有指令都不能使用缓存。因此 尽量将 ADD 指令放在 Dockerfile 的后面
  • 源路径可以有多个
  • 源路径是相对于执行build的相对路径
  • 源路径如果是本地路径,必须是 build 上下文中的路径
  • 源路径如果是一个目录,则该目录下的所有内容都将被加入到容器,但是该目录本身不会
  • 目标路径必须是绝对路径,或相对于 WORKDIR 的相对路径
  • 目标路径如果不存在,则会创建相应的完整路径
  • 目标路径如果不是一个文件,则必须使用 / 结束
  • 路径中可以使用通配符