Docker 教程(二):Dockerfile
你好,我是看山。
本文源自并发编程网的翻译邀请,翻译的是 Jakob Jenkov 的 《Docker 教程》 中的第二篇。
Dockerfile 包含一组关于如何构建 Docker 镜像的说明,通过docker build
命令执行 Dockerfile 文件,可以构建一个 Docker 镜像,本文介绍了如何编写 Dockerfile 文件以及构建一个 Docker 镜像。
Dockerfile 的好处
Dockerfile 文件以书面形式说明了如何构建一个 Docker 镜像,Docker 镜像通常包含如下内容:
首先需要一个基本的 Docker 镜像,在这个基础 Docker 镜像上构建自己的 Docker 镜像。
一组需要安装在 Docker 镜像中的工具和应用。
一组需要复制到 Docker 镜像中的文件(比如配置文件)。
可能需要在防火墙中打开的网络(TPC/UDP)端口或其他。
等等。。。
首先,在 Dockerfile 文件中以书面形式说明这些,就意味着,我们不用特意记住应用程序如何安装,包括操作系统什么要求、需要安装的应用程序、需要赋值的文件、需要打开的网络端口等,这些内容都被记录在 Dockerfile 中。
另外,通过 Dockerfile 文件构建 Docker 镜像,我们不需要手动执行这些繁琐重复且容易出错的工作。Docker 会自动做这些事情,简单、快速、且不容易出错。
第三,我们很容易和其他人分享 Dockerfile 文件,并且他们可以自己构建 Docker 镜像。
第四,Dockerfile 很容易存储在 Git 这样的版本控制器中,这样就可以跟踪 Dockerfile(服务器、应用配置)的变更记录。版本控制器也可以很容易的让人们协同合作,比如在 Dockerfile 上,以及分享 Dockerfile。
Dockerfile 的结构
Dockerfile 包含一组指令,每个指令有一个命令和参数组成,类似于命令行可执行文件。下面是一个 Dockerfile 简单示例:
Docker 基础镜像
Docker 镜像是由层组成,每一层都会为最终的 Docker 镜像添加一些内容。每一个层实际上都是一个单独的 Docker 镜像,所以说,Docker 镜像是由一个或多个层镜像组成,我们可以在其上添加自己的层。
当通过 Dockerfile 文件指定自己的 Docker 镜像时,通常是从一个 Docker 基础镜像开始。这是另一个 Docker 镜像,可以在其上构建自己的 Docker 镜像。这个 Docker 基础镜像本身可能也包含多个层,并且是基于另一个基础镜像构建的。
我们可以使用From
命令在 Dockerfile 文件中指定 Docker 镜像作为基础镜像,如下节所述。
MAINTAINER
MAINTAINER
命令用于说明谁在维护这个 Dockerfile 文件。比如:
MAINTAINER
命令并不常用,因为这类信息在 Git 存储或其他地方有了。
FROM
FROM
命令用于指定 Docker 基础镜像,如果是从原始 Linux 镜像开始,可以使用如下命令:
CMD
CMD
命令用于指定启动 Docker 容器是需要执行的命令,该容器是基于此 Dockerfile 构建的 Docker 镜像,下面是一些 Dockerfile 的CMD
示例:
本例是打印“Docker container started”这行文本。
下一个CMD
示例是启动一个 java 应用:
COPY
COPY
命令将一个或多个文件从主机(从 Dockerfile 文件构建 Docker 镜像的机器)复制到 Docker 镜像中,可以复制的内容包括文件或目录,下面是一个示例:
这个例子是把主机的/myapp/target/myapp.jar 文件复制到 Docker 进行中的/myapp/myapp.jar 文件。第一个参数是主机路径(从哪里来),第二个参数是 Docker 镜像的路径(到哪里去)。
我们还可以复制一个目录到 Docker 镜像中,比如:
这个例子是把主机的/myapp/config/prod 目录复制到 Docker 镜像中的/myapp/config 目录。
我们还可以复制多个文件到 Docker 镜像中的一个目录中,比如:
这个例子是将主机的/myapp/config/prod/conf1.cfg 文件和/myapp/conig/prod/conf2.cfg 文件复制到 Docker 镜像中的/myapp/config/目录中。注意,目标目录必须以/(斜杠)结束才能工作。
ADD
ADD
命令与COPY
命令工作方式相同,只有一些细微的差别:
ADD
命令可以复制并提取 TAR 文件到 Docker 镜像中。ADD
命令可以通过 HTTP 下载文件,并复制到 Docker 镜像中。
下是一些示例:
这个例子是将指定的 TAR 文件解压缩并提取到 Docker 镜像的/myapp/目录中。
下面是另一个例子:
ENV
ENV
命令是在 Docker 镜像中设置环境变量,此环境变量可用于CMD
命令在 Docker 镜像内部启动应用程序。举个例子:
本例将环境变量MY_VAR
设置为值 123。
RUN
RUN
可以在 Docker 镜像中执行命令行指令,执行时机是 Docker 镜像构建过程中,所以RUN
命令只会执行一次。RUN
命令可用于在 Docker 镜像中安装应用程序、提取文件或其他命令行功能,这些操作只需要执行一次,以供 Docker 镜像后续使用。
ARG
ARG
命令允许定义一个参数,这个参数可以在通过 Dockerfile 文件构建 Docker 镜像时,通过命令参数传递给 Docker。比如:
当执行docker build
命令执行 Dockerfile 构建 Docker 镜像时,可以指定tcpPort
参数,比如:
注意,
--build-arg
后面的tcpPort=8080
,是将tcpPort
参数的值设置为 8080。
我们可以通过多个ARG
命令定义多个参数,举个例子:
当构建 Docker 镜像时,必须为所有构建参数提供值。【译者注,1.13 版本之前,不提供值会直接报错,1.13 版本之后,不提供值不会报错,但是会弹出警告】。举个例子:
我们可以为ARG
设置默认值,当构建 Docker 镜像时,如果没有指定参数值,将使用默认值。举个例子:
如果tcpPort
和useTls
在生成 Docker 镜像时,都没有设置参数,将使用默认值 8080 和 true。
ARG
声明的参数通常在 Dockerfile 的其他地方引用,比如:
注意:两个引用
${tcpPort}
和${useTls}
,引用名是tcpPort
和useTls
这两个ARG
声明的参数。
WORKDIR
WORKDIR
命令指明了 Docker 镜像中的工作目录,工作目录将对WORKDIR
指令之后的所有命令生效,举个例子:
EXPOSE
EXPOSE
命令将对外开放 Docker 容器中的网络端口,比如,如果 Docker 容器运行一个 web 服务器,那么,该 web 服务器可能需要打开端口 80,以便客户端链接到它。举个例子:
我们还可以指明打开端口的通信协议,比如:UDP 和 TCP。下面是设置允许通信协议的示例:
如果没有指定协议,将默认认定为 TCP 协议。
VOLUME
VOLUME
命令会在 Docker 镜像中创建一个目录,这个目录可以挂载到 Docker 主机上。换句话说,可以在 Docker 镜像中创建目录,比如/data
,这个目录可以在稍后挂载到 Docker 主机的/container-data/container1
目录上。挂载成功后,容器会启动。下面是一个使用VOLUME
命令在 Dockerfile 中定义装载目录的示例:
ENTRYPOINT
ENTRYPOINT
命令为从该 Docker 镜像启动 Docker 容器提供入口点,入口点是 Docker 容器启动时执行的应用程序或命令。这样,ENTRYPOINT
和CMD
工作方式类似,不同之处在于,使用ENTRYPOINT
时,当ENTRYPOINT
执行的应用程序完成时,Docker 容器将关闭。因此,ENTRYPOINT
使 Docker 镜像本身成为一个可执行命令,可以启动,完成后关闭。以下是ENTRYPOINT
示例:
这个示例将在容器启动时执行 Java 应用程序的主类com.jenkov.myapp.Main
,当应用程序关闭时,Docker 容器也会关闭。
HEALTHCHECK
HEALTHCHECK
命令可以定期执行健康检查,以监视 Docker 容器中运行的应用程序的运行状况。如果命令返回 0,Docker 将认为应用程序和容器正常,如果命令返回 1,Docker 会认为应用程序和容器不正常。示例如下:
这个示例中使用了 java 应用程序的com.jenkov.myapp.HealthCheck
作为健康检查的命令,我们可以使用任何有意义的健康检查命令。
健康检查间隔时间
默认情况下,Docker 每 30 秒执行一次HEALTHCHECK
命令。如果想修改时间间隔,我们可以自定义时间,通过--interval
参数,可以指定健康检查的检查间隔时间。下面是一个将HEALTHCHECK
间隔设置为 60 秒的示例:
健康检查开始时间
默认情况下,Docker 会立即检查 Docker 容器的监控状况。但是,有些应用程序可能需要一段时间启动,因此,只有经过某段时间后再进行健康检查才有意义。我们可以使用--start-period
参数设置健康检查开始时间。下面是一个将健康检查设置为 5 分钟的示例,在 Docker 开始健康检查之前,为容器和应用程序提供 300 秒(5 分钟)的启动时间:
健康检查超时时间
健康检查很有可能超时,如果HEALTCHECK
命令需要超过给定时间限制才完成,Docker 将认为健康检查超时。可以使用--timeout
参数设置超时时间,如下是设置超时时间为 5 秒的示例:
注意,如果健康检查超时,Docker 也会认为容器不健康。
健康检查重复次数
如果HEALTHCHECK
命令执行失败,有可能是结果返回 1,或者执行超时,Docker 会在认定容器不健康前,重试 3 次HEALTHCHECK
命令,用于检查 Docker 容器是否返回健康状态。可以通过--retries
设置重试次数。下面是将重试次数设置为 5 的示例:
你好,我是看山,公众号:看山的小屋,10 年老猿,Apache Storm、WxJava、Cynomys 开源贡献者。游于码界,戏享人生。
版权声明: 本文为 InfoQ 作者【看山】的原创文章。
原文链接:【http://xie.infoq.cn/article/7a6314577b32bd0fb4316f2cf】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论