Dockerfile使用手册

在Dockerfile中,指令不区分大小写,但是为了与参数区分,推荐大写。Docker会顺序执行Dockerfile中的指令,第一条指令必须是FROM指令,它用于构建镜像的基础镜像。在Dockerfile中以#开头的行是注释,而在其他位置出现的#会被当成参数。

Dockerfile中的指令有FROM、MAINTAINER、RUN、CMD、EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、ONBUILD,错误的指令会被忽略,下面将详细讲解一些重要的Docker指令。

  1. ENV
格式: ENV  或ENV = ...

ENV指令可以为镜像创建出来的容器声明环境变量。并且在Dockerfile中,ENV指令声明的环境变量会被后面的特定指令(即ENV、ADD、COPY、WORKDIR、EXPOSE、VOLUME、USER)解释使用。其他指令使用环境变量时,使用格式为$variable_name或者${variable_name}。在变量前面添加斜线\可以转义。另外,ONBUILD指令不支持环境变量。

  1. FROM
格式: FROM  或 FROM :

FROM指令的功能是为后面的指令提供基础镜像,因此一个有效的Dockerfile必须以FROM指令作为第一条非注释指令。在一个Dockerfile中,FROM指令可以出现多次,这样会构建多个镜像。

  1. COPY
格式:COPY  

COPY指令复制所指向的文件或目录,将它添加到新镜像中,复制的文件或目录在镜像中的路径是所指定的源可以有多个,但必须在上下文中,即必须是上下文根目录的相对路径。不能使用形如COPY ../something /something这样的指令。此外,可以使用通配符指向所有匹配通配符的文件或目录,例如,COPY hom* /mydir/表示添加所有以"hom"开头的文件到目录/mydir/中。

可以是文件或目录,但必须是目标镜像中的绝对路径或者相对于WORKDIR的相对路径(WORKDIR即Dockerfile中WORKDIR指令指定的路径,用来为其他指令设置工作目录)。若以反斜线/结尾则其指向的是目录;否则指向文件。同理。若是一个文件,则的内容会被写入到中;否则指向的文件或目录中的内容会被复制添加到目录中。当指定多个源时,必须是目录。另外,如果不存在,则路径中不存在的目录会被创建。

  1. ADD
格式:ADD  

ADD与COPY指令在功能上很相似,都支持复制本地文件到镜像的功能,但ADD指令还支持其他功能。可以是一个指向网络文件的URL,此时若指向一个目录,则URL必须是完全路径,这样可以获取该网络文件的文件名filename,该文件名被复制添加到/。例如,ADD http://example.com/foobar / 会创建文件/foobar。

还可以指向一个本地压缩归档文件,该文件在复制到容器中时会被解压提取,如ADD example.tar.xz /。但若URL中的文件为归档文件则不会被解压提取。
ADD和COPY指令虽然功能相似,但一般推荐使用COPY,因为COPY只支持本地文件,相比ADD而言,它更透明。

  1. RUN
RUN的格式有两种
RUN  (shell格式)
RUN ["executable", "param1", "param2"](exec格式,推荐格式)

RUN指令会在前一条命令创建出的镜像基础上创建一个容器,并在容器中运行命令,在命令结束运行后提交容器为新镜像,新镜像被Dockerfile中的下一条指令使用。

RUN指令的两种格式表示命令在容器中的两种运行方式。当使用shell格式时,命令通过/bin/sh -c运行;当使用exec格式时,命令是直接运行的,容器不调用shell程序,及容器中没有shell程序。exec格式中的参数会当初JSON数组被Docker解析,故需要使用双引号而不能使用单引号。因为exec格式不会再shell中执行,所以环境变量的参数不会被替换,例如,当执行RUN ["echo", "$HOME"]指令时,$HOME不会做变量替换。如果希望运行shell程序,指令可以写成RUN ["sh", "-c", "echo", "$HOME"]。

  1. CMD
CMD指令有三种格式:
CMD  (shell格式)
CMD ["executable", "param1", "param2"] (exec格式,推荐格式)
CMD ["param1", "param2"] (为ENTRYPOINT指令提供参数)

CMD指令提供容器运行时的默认值,这些默认值可以是一条指令,也可以是一些参数。一个Dockerfile中可以有多条CMD指令,但只有最后一条CMD指令有效。CMD ["param1", "param2"]格式是在CMD指令和ENTRYPOINT指令配合时使用的,CMD指令中的参数会添加到ENTRYPOINT指令中。使用shell和exec格式时,命令在容器中的运行方式与RUN指令相同。不同在于,RUN指令在构建镜像时执行命令,并生成新的镜像;CMD指令在构建镜像时不执行任何命令,而是在容器启动是默认将CMD指令作为第一条执行的命令。如果用户在命令行界面运行docker run命令时指定了命令参数,则会覆盖CMD指令中的命令。

  1. ENTRYPOINT
ENTRYPOINT指令有两种格式:
ENTRYPOINT  (shell格式)
ENTRYPOINT ["executable", "param1", "param2"] (exec格式,推荐格式)

ENTRYPOINT指令和CMD指令类似,都可以让容器在每次启动时执行相同的指令,但它们之间又有不同。一个Dockerfile中可以有多条ENTRYPOINT指令,但只有最后一条ENTRYPOINT指令有效。当使用shell格式时,ENTRYPOINT指令会忽略CMD指令和docker run命令的参数,并且会运行在/bin/sh -c中。这意味着ENTRYPOINT指令进程为/bin/sh -c的子进程,进程在容器中国的PID将不是1,且不能接受Unix信号。即当使用docker stop 命令时,命令进程接收不到SIGTERM信号。我们推荐使用exec格式,使用此格式时,docker run传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT指令的参数中。从ENTRYPOINT的使用中可以看出,CMD可以是参数,也可以是指令,而ENTRYPOINT只能是命令;另外docker run命令提供的命令行参数可以覆盖CMD,但不能覆盖ENTRYPOINT。

  1. ONBUILD
格式: ONBUILD [INSTRUCTION]

ONBUILD指令的功能是添加一个将来执行的触发器指令到镜像中。当该镜像作为FROM指令的参数时,这些触发器命令就会在FROM指令执行时加入到构建过程中。尽管任何指令都可以注册成一个触发器指令,但ONBUILD指令中不能包含ONBUILD指令,并且不会触发FROM和MAINTAINER指令。当需要制作一个基础镜像来构建其他镜像时,ONBUILD是很有用的。例如,当需要构建的镜像是一个可重复使用的Python环境镜像时,它可能需要将应用源代码加入到一个指定目录中,还可能需要执行一个构建脚本。此时不能仅仅调用ADD和RUN指令,因为现在还不能访问应用源代码。

并且不同应用的源代码是不同的。我们不能简单地提供一个Dockerfile模板给应用开发者,它与特定应用代码耦合,会引发低效、易错、难以更新等问题。这些场景的解决方案是使用ONBUILD指令注册触发器指令,利用ONBUILD指令构建一个语言栈镜像,该镜像可以构建任何用语言编写的用户软件的镜像。

ONBUILD指令的具体执行步骤如下:

  1. 在构建过程中,ONBUILD指令会添加到触发器指令镜像元数据中。这些触发器指令不会在当前构建过程中执行。
  2. 在构建过程最后,触发器指令会被存储在镜像详情中,其主键是OnBuild,可以使用docker inspect命令查看。
  3. 之后镜像可能作为其他Dockerfile中FROM指令的参数。在构建过程中,FROM指令会寻找ONBUILD触发器指令,并且会以他们注册的顺序执行。若有触发器指令执行失败,则FROM指令被终止,并返回失败;若所有触发器指令执行成功,则FROM指令完成并继续执行下面的指令。在镜像构建完成后,触发器指令会被清除,不会被子孙镜像继承。

使用包含ONBUILD指令的Dockerfile构建的镜像应该有特殊的标签,如ruby:2.0-onbuild。在ONBUILD指令中添加ADD或COPY指令时要额外注意。假如新构建过程的上下文缺失了被添加的资源,那么新构建过程会失败。给ONBUILD镜像添加标签,可以提示编写Dockerfile的开发人员小心应对。

你可能感兴趣的:(Dockerfile使用手册)