《Docker 教程》(二):Dockerfile

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简单示例:

# 基础镜像
FROM ubuntu:latest

# 这里可以有更多安装软件和复制文件到镜像中的说明。
COPY    /myapp/target/myapp.jar    /myapp/myapp.jar

# 在Docker容器中执行的命令。
CMD echo Starting Docker Container

Docker基础镜像

Docker镜像是由层组成,每一层都会为最终的Docker镜像添加一些内容。每一个层实际上都是一个单独的Docker镜像,所以说,Docker镜像是由一个或多个层镜像组成,我们可以在其上添加自己的层。

当通过Dockerfile文件指定自己的Docker镜像时,通常是从一个Docker基础镜像开始。这是另一个Docker镜像,可以在其上构建自己的Docker镜像。这个Docker基础镜像本身可能也包含多个层,并且是基于另一个基础镜像构建的。

我们可以使用From命令在Dockerfile文件中指定Docker镜像作为基础镜像,如下节所述。

MAINTAINER

MAINTAINER命令用于说明谁在维护这个Dockerfile文件。比如:

MAINTAINER   Joe Blocks <joe@blocks.com>

MAINTAINER命令并不常用,因为这类信息在Git存储或其他地方有了。

FROM

FROM命令用于指定Docker基础镜像,如果是从原始Linux镜像开始,可以使用如下命令:

# 基础镜像
FROM ubuntu:latest

CMD

CMD命令用于指定启动Docker容器是需要执行的命令,该容器是基于此Dockerfile构建的Docker镜像,下面是一些Dockerfile的CMD示例:

CMD echo Docker container started.

本例是打印“Docker container started”这行文本。

下一个CMD示例是启动一个java应用:

CMD java -cp /myapp/myapp.jar com.jenkov.myapp.MainClass arg1 arg2 arg3

COPY

COPY命令将一个或多个文件从主机(从Dockerfile文件构建Docker镜像的机器)复制到Docker镜像中,可以复制的内容包括文件或目录,下面是一个示例:

COPY    /myapp/target/myapp.jar    /myapp/myapp.jar

这个例子是把主机的/myapp/target/myapp.jar文件复制到Docker进行中的/myapp/myapp.jar文件。第一个参数是主机路径(从哪里来),第二个参数是Docker镜像的路径(到哪里去)。

我们还可以复制一个目录到Docker镜像中,比如:

COPY    /myapp/config/prod    /myapp/config

这个例子是把主机的/myapp/config/prod目录复制到Docker镜像中的/myapp/config目录。

我们还可以复制多个文件到Docker镜像中的一个目录中,比如:

COPY    /myapp/config/prod/conf1.cfg   /myapp/config/prod/conf2.cfg   /myapp/config/

这个例子是将主机的/myapp/config/prod/conf1.cfg文件和/myapp/conig/prod/conf2.cfg文件复制到Docker镜像中的/myapp/config/目录中。注意,目标目录必须以/(斜杠)结束才能工作。

ADD

ADD命令与COPY命令工作方式相同,只有一些细微的差别:

  • ADD命令可以复制并提取TAR文件到Docker镜像中。
  • ADD命令可以通过HTTP下载文件,并复制到Docker镜像中。

下是一些示例:

ADD    myapp.tar    /myapp/

这个例子是将指定的TAR文件解压缩并提取到Docker镜像的/myapp/目录中。

下面是另一个例子:

ADD    http://jenkov.com/myapp.jar    /myapp/

ENV

ENV命令是在Docker镜像中设置环境变量,此环境变量可用于CMD命令在Docker镜像内部启动应用程序。举个例子:

ENV    MY_VAR   123

本例将环境变量MY_VAR设置为值123。

RUN

RUN可以在Docker镜像中执行命令行指令,执行时机是Docker镜像构建过程中,所以RUN命令只会执行一次。RUN命令可用于在Docker镜像中安装应用程序、提取文件或其他命令行功能,这些操作只需要执行一次,以供Docker镜像后续使用。

RUN apt-get install some-needed-app

ARG

ARG命令允许定义一个参数,这个参数可以在通过Dockerfile文件构建Docker镜像时,通过命令参数传递给Docker。比如:

ARG tcpPort

当执行docker build命令执行Dockerfile构建Docker镜像时,可以指定tcpPort参数,比如:

docker build --build-arg tcpPort=8080 .

注意,--build-arg后面的tcpPort=8080,是将tcpPort参数的值设置为8080。

我们可以通过多个ARG命令定义多个参数,举个例子:

ARG tcpPort
ARG useTls

当构建Docker镜像时,必须为所有构建参数提供值。【译者注,1.13版本之前,不提供值会直接报错,1.13版本之后,不提供值不会报错,但是会弹出警告】。举个例子:

docker build --build-arg tcpPort=8080 --build-arg useTls=true .

我们可以为ARG设置默认值,当构建Docker镜像时,如果没有指定参数值,将使用默认值。举个例子:

ARG tcpPort=8080
ARG useTls=true

如果tcpPortuseTls在生成Docker镜像时,都没有设置参数,将使用默认值8080和true。

ARG声明的参数通常在Dockerfile的其他地方引用,比如:

ARG tcpPort=8080
ARG useTls=true

CMD start-my-server.sh -port ${tcpPort} -tls ${useTls}

注意:两个引用${tcpPort}${useTls},引用名是tcpPortuseTls这两个ARG声明的参数。

docker build --build-arg tcpPort=8080

WORKDIR

WORKDIR命令指明了Docker镜像中的工作目录,工作目录将对WORKDIR指令之后的所有命令生效,举个例子:

WORKDIR    /java/jdk/bin

EXPOSE

EXPOSE命令将对外开放Docker容器中的网络端口,比如,如果Docker容器运行一个web服务器,那么,该web服务器可能需要打开端口80,以便客户端链接到它。举个例子:

EXPOSE   8080

我们还可以指明打开端口的通信协议,比如:UDP和TCP。下面是设置允许通信协议的示例:

EXPOSE   8080/tcp 9999/udp

如果没有指定协议,将默认认定为TCP协议。

VOLUME

VOLUME命令会在Docker镜像中创建一个目录,这个目录可以挂载到Docker主机上。换句话说,可以在Docker镜像中创建目录,比如/data,这个目录可以在稍后挂载到Docker主机的/container-data/container1目录上。挂载成功后,容器会启动。下面是一个使用VOLUME命令在Dockerfile中定义装载目录的示例:

VOLUME   /data

ENTRYPOINT

ENTRYPOINT命令为从该Docker镜像启动Docker容器提供入口点,入口点是Docker容器启动时执行的应用程序或命令。这样,ENTRYPOINTCMD工作方式类似,不同之处在于,使用ENTRYPOINT时,当ENTRYPOINT执行的应用程序完成时,Docker容器将关闭。因此,ENTRYPOINT使Docker镜像本身成为一个可执行命令,可以启动,完成后关闭。以下是ENTRYPOINT示例:

ENTRYPOINT java -cp /apps/myapp/myapp.jar com.jenkov.myapp.Main

这个示例将在容器启动时执行Java应用程序的主类com.jenkov.myapp.Main,当应用程序关闭时,Docker容器也会关闭。

HEALTHCHECK

HEALTHCHECK命令可以定期执行健康检查,以监视Docker容器中运行的应用程序的运行状况。如果命令返回0,Docker将认为应用程序和容器正常,如果命令返回1,Docker会认为应用程序和容器不正常。示例如下:

HEALTHCHECK java -cp /apps/myapp/healthcheck.jar com.jenkov.myapp.HealthCheck https://localhost/healthcheck

这个示例中使用了java应用程序的com.jenkov.myapp.HealthCheck作为健康检查的命令,我们可以使用任何有意义的健康检查命令。

健康检查间隔时间

默认情况下,Docker每30秒执行一次HEALTHCHECK命令。如果想修改时间间隔,我们可以自定义时间,通过--interval参数,可以指定健康检查的检查间隔时间。下面是一个将HEALTHCHECK间隔设置为60秒的示例:

HEALTHCHECK --interval=60s java -cp /apps/myapp/healthcheck.jar com.jenkov.myapp.HealthCheck https://localhost/healthcheck

健康检查开始时间

默认情况下,Docker会立即检查Docker容器的监控状况。但是,有些应用程序可能需要一段时间启动,因此,只有经过某段时间后再进行健康检查才有意义。我们可以使用--start-period参数设置健康检查开始时间。下面是一个将健康检查设置为5分钟的示例,在Docker开始健康检查之前,为容器和应用程序提供300秒(5分钟)的启动时间:

HEALTHCHECK --start-period=300s java -cp /apps/myapp/healthcheck.jar com.jenkov.myapp.HealthCheck https://localhost/healthcheck

健康检查超时时间

健康检查很有可能超时,如果HEALTCHECK命令需要超过给定时间限制才完成,Docker将认为健康检查超时。可以使用--timeout参数设置超时时间,如下是设置超时时间为5秒的示例:

HEALTHCHECK --timeout=5s java -cp /apps/myapp/healthcheck.jar com.jenkov.myapp.HealthCheck https://localhost/healthcheck

注意,如果健康检查超时,Docker也会认为容器不健康。

健康检查重复次数

如果HEALTHCHECK命令执行失败,有可能是结果返回1,或者执行超时,Docker会在认定容器不健康前,重试3次HEALTHCHECK命令,用于检查Docker容器是否返回健康状态。可以通过--retries设置重试次数。下面是将重试次数设置为5的示例:

HEALTHCHECK --retries=5 java -cp /apps/myapp/healthcheck.jar com.jenkov.myapp.HealthCheck https://localhost/healthcheck

你好,我是看山,公众号:看山的小屋,10 年老猿,Apache Storm、WxJava、Cynomys 开源贡献者。游于码界,戏享人生。

原文链接:Docker Dockerfile

翻译:https://www.howardliu.cn

译文链接:Docker 教程(二):Dockerfile

公众号:看山的小屋

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 《Docker 教程》(二):Dockerfile

  • Trackback 关闭
  • 评论 (0)
  1. 暂无评论

return top