今天我们继续学习Docker技术。本文主要介绍Dockerfile。Dockerffile是一个文本文件。Docker通过读取Dockerfile文件自动构建镜像。接下来程哥就给大家介绍一下Dockerfile的语法和用法!01Dockerfile概述Dockerfile相当于一个文档,用户可以基于Dockerfile生产新的容器。Dockerfile只是一个用来制作镜像的源代码文件。它是构建容器过程中的指令。Docker可以读取dockerfile的指令自动构建容器。基于dockerfile做镜像,每条指令都会创建一个镜像层,也就是有多少个镜像层?层数叠加,镜像层数越多,效率越低。因此,在创建镜像时,尽量用尽可能少的指令来完成所需的动作。Docker通过dockerfile进行构建,构建后的镜像运行流程逻辑如下图所示。02编写Dockerfile(一)Contextcontext是指我们构建Docker镜像时Dockerfile文件所在的目录。构建镜像由Docker守护进程而不是CLI运行。流程中的第一件事就是将目录下的Dockerfile文件全部内容递归发送给daemon。所以在大多数情况下,最好创建一个新目录,将Dockerfile保存在里面,并在那里添加构建Dockerfile所需的文件。现在我们在系统中创建一个空目录,用于创建下面的Dockerfile和后续的镜像构建(2)Dockerfile格式Dockerfile的语法格式如下:1.#格式为syntax+parameters2.INSTRUCTIONarguments这条指令的作用不区分大小写。但是,惯例是将它们大写,以便更容易将它们与参数区分开来。Dockerfile按顺序运行指令。(3)Dockerfile常用命令1)FROM一个Dockerfile必须以FROM命令开头。使用FROM命令指定一个基础镜像,后续命令将基于该镜像运行。FROM可以在Dockerfile中出现多次。我们看一下FROM的语法格式1.FROM[--platform=][AS]我们创建一个Dockerfile,其中FROM指定centos为基础镜像1.#指定centos作为build2的基础镜像。FROMcentos2)WORKDIRWORKDIR用于指定工作目录,所有执行的shell语句都会在指定的目录下运行,后面要讲的RUN、CMD、COPY、ADD命令都会在指定的工作目录下执行。这条指令在一个Dockerfile中也可以出现多次,最后出现的目录是上一个目录的子目录。如下图:1.WORKDIR/a2.WORKDIRb3.WORKDIRc4.RUNpwd最后一个pwd命令执行的目录是/a/b/c。我们继续按照上面的说明将WORKDIR目录指定为'/'。3)RUNRUN指令用于执行命令。该指令有两种形式:a.RUN,使用shell执行指定的command命令,默认的shell是/bin/sh-cb。RUN["executable","param1","param2"],使用可执行文件或程序后跟相关参数,按照以下两种形式创建执行命令1.#firstARUN指令方法2.RUNyumupdate3.4.#第二种RUN指令方式5.RUN["/bin/bash","-c","echohello"]4)CMDCMD的使用与RUN类似,与RUN类似,区别在于执行RUN镜像构建时,CMD是容器运行后执行的命令。一个Dockerfile中只能有一个CMD命令,如果有多个CMD命令,则只有最后一个命令生效。CMD也有三种命令格式,具体如下1.#第一种执行命令的推荐用法2.CMD["executable","param1","param2"]3.4.#第二种格式主要与ENTRYPOINT一起使用,即CMDcommand的值会作为ENTRYPOINT指令的参数5.CMD["param1","param2"]6.7.#第三种方法执行shellform,与第一种方法执行效果一致8.CMDcommandparam1param2我们通过第一种方法创建执行wc的帮助说明如下:1.CMD["/usr/bin/wc","--help"]第二种方法需要用到Dockerfile中的ENTRYPOINT指令,ENTRYPOINT指令会在容器运行时将CMD指令覆盖为默认指令。说明,dockerrun时不会被覆盖,如下例所示1.FROMcentos2.ENTRYPOINT["ls","-a"]3.CMD["-l"]上面构建的镜像等同于我们使用dockerrun基于dockerrunls-al命令。CMD命令的值会作为ENTRYPOINT命令的参数附加到ENTRYPOINT命令中,如果在dockerrun中指定了该参数,它将覆盖CMD中给出的参数。5)COPY&ADDCOPY和ADD都是用来拷贝文件、目录等到镜像中。两者的区别在于ADD可以使用远程URL路径作为复制源。如果只复制本地文件,建议使用COPY。两条命令的语法格式如下:1.#ADD命令格式2.ADD[--chown=:]...3.ADD[--chown=:]["",...""]4.5.#COPY命令格式6.COPY[--chown=:]。..7.COPY[--chown=:]["",..""]--chown用于指定文件目录的用户和权限。可以指定多个,但路径不能超过context的路径,即必须和Dockerfile在同一层级或子目录下。不需要预先存在,如果路径不存在会自动创建,如果没有使用绝对路径,则为WORKDIR指定目录的相对路径。6)ENVENV用于定义Dockerfile的环境变量,该变量设置的值会在build阶段后续所有指令的环境中使用,很多情况下也可以inline替换。命令格式如下:1.ENV=...使用示例如下1.#$MYDIR将替换为“/mydir”2.ENVMYDIR="/mydir"3.RUNmkdir$MYDIR7)forVOLUMEVOLUME在Dockerfile中指定挂载目录时,容器运行时会自动创建对应的匿名卷。命令格式如下:1.VOLUME["/data"]该命令会在容器运行时创建一个匿名卷,将容器中的/data目录挂载到该卷中。8)EXPOSEEXPOSE命令告诉Docker容器在运行时监听指定的网络端口。您可以指定端口是监听TCP还是UDP,如果没有指定协议,则默认为TCP。EXPOSE指令实际上并不发布端口。它充当构建图像的人和运行容器的人之间的一种文档,关于要发布哪些端口。如果要暴露容器端口,需要在dcokerrun命令中使用-p。EXPOSE指令格式及使用示例如下:1.#EXPOSE命令格式2.EXPOSE[/...]3.4.#让容器同时监听TCP和UDP80端口time5.EXPOSE80/tcp6.EXPOSE80/udp03Dockerfile镜像构建我们现在使用Dockerfile搭建一个nginx服务器。Dockerfile的具体配置如下:1.#指定基础镜像2.FROMcentos3.4.#设置环境目录5.WORKDIR/6.7.#安装nginx8.RUNyuinstallnginx-y9.10.#Container将80端口暴露给outsideworld11.EXPOSE8012.13.#Startnginx14.CMD["/usr/sbin/nginx","-g","daemonoff;"]然后通过Dockerfile文件构建镜像,具体如下。最后我们启动容器,查看nginx服务是否可以访问。具体操作如下