本文转载自微信公众号《小浪代码答案》,作者浪同学。转载本文请联系小浪码答公众号。前言大家好,我是郎朗,一个每天都想学一点点的年轻人。最近几天,项目很忙。你在忙什么?一方面忙于项目的三轮测试,另一方面忙于将项目组的后台服务迁移上云。作为后端开发工程师,写了一个星期的Shell脚本,哎呀,太酸了,想重温一遍。最让我反感的是公司自研的容器云平台一点都不稳定(听说容器云团队要把底层语言Java转Go,导致容器缺乏维护云平台一段时间)。在容器云平台构建镜像时,经常会因为拉取jar包超时而导致构建失败。当我终于完成构建,终于来到各种应用服务和中间件安排的时候,我还需要检查各种依赖、端口和IP。一个一个的配置环境变量,真是想死,停不下来。不过经过这个项目,我的shell编程能力达到了一个前所未有的高度(虽然在外人看来还是很不错的)。我写得最多的是Dockerfile。以前一直觉得Dockerfile构建镜像很好。写多了,来回找命令。难点在于shell编程中的反人类语法。今天下班早,总结一下Dockerfile。知识点,希望对大家有所帮助。一、Dockerfile的原理在学习Dockerfile之前,我们需要了解Dockerfile、Docker镜像和Docker容器之间的关系。容器化Docker的核心思想是将应用程序容器化。应用容器化通常分为以下几个步骤:(1)编写应用代码(2)编写Dokcerfile脚本,其中包含当前应用的描述、依赖关系以及如何运行应用(3)执行dockerimagebuild命令在Dockerfile脚本上,构建镜像(4)完成的镜像用于完成容器化过程。所以写一个优秀的Dockerfile对于构建镜像是必不可少的。DockerFile是一个包含一系列用于构建docker镜像的命令和参数的文件。Docker可以读取Dockerfile指定的指令并自动构建它。从上到下的每条指令都会创建一个镜像层,即镜像是多层的。因此,层数越多,用尽可能少的层数创建镜像的效率就越低。因此,能用一条命令完成的动作,尽量用一条命令来定义。在Dockerfile中编写指令的过程中,需要确定制作镜像的目录,即包含Dockerfile文件的目录,通常称为buildcontext。注意:Dockerfile文件必须以字母D开头。接下来让我们在学习Dockerfile命令的过程中了解镜像的构建。2.Dockerfile的常用命令先来看一张Dockerfile指令表的指令函数。FROM构建镜像使用的基础镜像MAINTAINER设置镜像作者RUN编译镜像时需要运行的命令CMD镜像启动命令LABEL设置镜像启动标签EXPOSE设置镜像暴露端口ENV设置镜像的环境变量containerADD编译镜像时复制文件到镜像COPY编译镜像时复制文件到镜像(区别于ADD命令)ENTRYPOINT容器入口程序VOLUME设置容器挂载卷USER执行命令的用户名称WORKDIR输入容器的目录ARG。编译镜像的时候好像加了很多参数说明。其实也不难理解。下面,我们将对这些指令一一进行说明。2.1FROM每个Dockerfile的第一行是FROM指令。FROM命令指定的镜像将作为当前镜像的基础镜像图像层格式:FROM#默认最新版镜像FROM[:]#指定tag版本镜像FROM[@]#使用加密摘要获取镜像2.2MAINTAINER这条指令用于判断维护镜像的作者信息的格式为:MAINTAINER该命令目前已经废弃,可以使用命令LABELLABELuser="simon"key2="value2"可以表示多个信息通过多个键值对2.3RUNRUN命令是构建镜像时使用的命令格式:RUNRUN["executable","param1","param1"]第一种格式是在shell终端运行,即is,/bin/sh-c(default);NOTE:bashandbash-cbash-c后接可执行命令bash后接可执行脚本第二种格式类似函数调用,executable可以理解为可执行程序,后接两个参数例如:RUNyuminstall-yvimRUN["/bin/bash","-c","yuminstall-yvim"]每个RUN规范会在当前镜像的基础上执行指定的命令,并作为新镜像提交。当命令较长时,可以用\来换行2.4CMDCMD命令是容器启动时运行的命令使用格式:CMD["executable","param1","param2"]CMD["param1","param2"]CMDcommandparam1param2第一种格式和第二种格式是一个可执行程序加一个参数的形式例子CMD["bash","-c,"jav-jardemo_application.jar"]CMD["java-jar","demo_application.jar"]第三种比较简单的CMDJava-jardemo_application.jar2.5LABELLABEL为图片指定标签LABEL===...我们经常使用LABEL指令代替MAINTAINER指令2.6EXPOSEEXPOSE是暴露容器运行时的端口,但是EXPOSE不会让容器访问宿主机的端口。如果想容器与宿主机的端口有映射关系,必须在容器启动时加上-P参数使用格式:EXPOSE8848#NACOSEXPOSE8070#APOLLO2.7ENVENV是设置环境变量,供脚本使用。使用格式:ENVENV=..2.8ADDADD是复制命令,复制Dockerfile上下文目录中的文件/路径使用格式复制到容器的指定目录:ADD...ADD["",...""]src指的是上下文目录文件,dest指的是容器中的路径注意:复制压缩文件时文件,使用ADD命令自定义解压ADD可以将url复制到容器中2.9COPYCOPY与ADD类似,将文件和目录复制到容器中,可以从复制<原始路径>中的文件/目录将上下文目录构建到新层图像中的位置。格式:COPYsrcdestCOPY["",...""]2.10ENTRYPOINTENTRYPOINT和CMD命令类似,在容器启动时执行。格式:ENTRYPOINT["executable","param1","param2"]ENTRYPOINTcommandparam1param22.11VOLUMEVOLUME命令实现挂载功能,用于定义容器运行时可以挂载到宿主机上。目录格式:VOLUME["/data"]2.12USERUSER设置启动容器的用户格式:USERsimongsimonsimon为用户,gsimon为用户组2.1.3WORKDIRWORKDIR设置容器中的工作目录。容器创建后,终端会默认登录工作目录。使用格式:WORKDIR/path/to/workdir3、一个简单的Dockerfile文件示例3.1写Dockerfile文件#基于哪个镜像fromjava:8#暴露端口EXPOSE8080#创建工作目录RUNmkdir-p/com/simon/study#复制文件到containerADDtarget/demo_application.jar/com/simon/study#进入工作目录WORKDIR/com/simon/study#配置容器启动后执行的命令ENTRYPOINT["java","-jar","demo_application.jar"]3.2使用dockerbuild命令构建镜像dockerbuild-tdemo_application:v1.0dockerbuild-timagename:label,使用-t选项指定镜像的label。3.3启动镜像dockerrun-p8080:8080demo-application:v1.04。小结本文仅简单介绍Dockerfile的使用,对云端不作具体介绍。其实写云脚本不仅仅是写Dockerfile,还涉及到其他脚本的使用。与其他脚本相比,Dockerfile非常简单,因为其他脚本还需要编写大量的中间件环境变量、用户/目录授权、SSL证书检测等等。如果你对上云感兴趣,可以私信我,相信我能帮到你!