2.Dockefile构建原理在之前的学习中,我们了解到可以将运行起来的容器通过commit打包为一个镜像,但是这种方法仅限于在已有容器的基础上,并且具有一定的局限性。于是便产生了Dockerfile构建镜像。
Dockerfile是一种Docker镜像的描述文件,是由一系列命令和参数构成的脚本。它主要作用是用来构建docker镜像的构建文件。Dockerfile文件在构建时,按照指令顺序由上到下依次执行,每条指令都会基于上一层创建并叠加一个新的镜像层,并对镜像进行提交。最终得到我们定制的镜像。
3.Dockerfile构建指令Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为 Docker Remote API,而如 docker 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 docker 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举。
在构建的时候,用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。然后服务器会解析dockerfile文件,并自动执行其中的指令,来构建我们定制的镜像。
# docker build [OPTIONS] [PATH | URL | -]
- OPTIONS:
- -f : 显式指定构建镜像的 Dockerfile 文件名称(Dockerfile 可不在上下文目录中),若不指明则默认为当前目录下的 'Dockerfile'
- -t : 指明docker镜像的名称和版本号 imag:tag
- 上下文路径|URL:指定构建镜像的上下文目录路径。docker会将上下文目录的所有内容作为镜像环境全部打包发给服务器,构建镜像的过程中,可以且只可以引用上下文中的任何文件(但是上下文目录并不封装到镜像中,只是作为镜像构建的服务器目录环境) 。因此,在实际开发中通常创建一个空目录来放置Dockerfile,并使用 . 指定当前目录作为上下文目录。
#举例子 docker build -f mydockerfile -t mycentos:1.0 .二.Dockerfile指令详解 1.FROM
FROM指令用来指定构建的基础镜像。所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令。其语法如下:
FROM
:
#举例子 FROM centos:7
2.RUN
- FROM指定构建镜像的基础源镜像,如果本地没有指定的镜像,则会自动从 Docker 的公共库 pull 镜像下来。
- FROM必须是 Dockerfile 中非注释行的第一个指令,即一个 Dockerfile 从FROM语句开始。
- FROM可以在一个 Dockerfile 中出现多次,如果有需求在一个 Dockerfile 中创建多个镜像。
- 如果FROM语句没有指定镜像标签,则默认使用latest标签。
RUN指令用于在构建镜像时,将在当前镜像层基础上执行指定命令(如yum下载安装、文件处理、环境配置等等),并提交为新的镜像层,后续的RUN都以之前RUN提交后的镜像为基础。RUN 指令在定制镜像时是最常用的指令之一。其语法如下:
- shell 格式:RUN <命令> 比如:RUN yum install vim
- exec 格式:RUN ["可执行文件", "参数1", "参数2"](不要使用单引号) 比如:RUN ["yum","install","vim"]
#例子:定制镜像时安装vim和wget(等同于,在终端操作的 shell 命令。) FROM centos:7 RUN yum install -y vim RUN ["yum","install","-y","net-tools"]
改进:dockerfile支持以 && 连接多条指令,行尾添加 的命令换行,以及行首 # 进行注释的格式,这样我们可以将多条RUN命令串联起来,将两层镜像层简化为一层,缩小镜像体积减少镜像臃肿。
#例子:定制镜像时安装vim和wget(等同于,在终端操作的 shell 命令。)
FROM centos:7
RUN yum install -y vim
&& yum install -y net-tools
3.WORKDIR
使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录,即刚入容器时所在的目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。其语法为:
- WORKDIR <工作目录路径>
FROM centos:7 WORDIR /usr
4.ENV注意:
- 不要使用RUN cd 来指定变更工作目录:由于Docker是分层的,RUN的执行仅仅是当前进程的工作目录变更,一个内存上的变化而已,其结果不会造成任何文件变更。而到第二层的时候,启动的是一个全新的容器,跟第一层的容器更完全没关系,自然不可能继承前一层构建过程中的内存变化。
- 可以使用多个WORKDIR指令:后续命令如果参数是相对路径,则会基于之前命令指定的路径。
这个指令很简单,就是设置环境变量而已,无论是后面的其它指令,如 RUN,还是运行时的应用,都可以直接使用这里定义的环境变量。其语法如下:
- ENV
# 只能设置一个变量 - ENV
= = ... #允许一次设置多个变量
#ENV 定义环境变量 ENV NODE_VERSION 7.2.0 # $NODE_VERSION 调用环境变量 RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"5.EXPOSE
6.VOLUMEEXPOSE 指令是声明运行时容器提供的服务端口。这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。该指令仅仅是声明我们这个镜像中打算使用哪些端口,并没有实质性的作用,只是便于开发人员理解和维护镜像配置。我们还是要通过 -p 来公开映射外部访问端口。其语法如下:
- EXPOSE <端口1> [ <端口2>... ]
为了防止启动容器时用户忘记将动态文件所保存目录挂载为数据卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,则相应目录会自动挂载到一个匿名数据卷上。其语法为:
- VOLUME ["<路径1>", "<路径2>"...] #多路径挂载
- VOLUME <路径> #单路径挂载
#匿名挂载 VOLUME /data #容器启动 docker run -d xxx #/data 目录就会在运行时自动挂载为匿名卷 docker run -d -v mydata:/data xxxx #mydata 这个命名卷替代了Dockerfile 中定义的匿名卷的挂载配置。7.COPY
COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。其语法如下:
- COPY [--chown=
: ] <源路径>... <目标路径> - COPY [--chown=
: ] ["<源路径1>",... "<目标路径>"] 注意:
- <源路径> 可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的 filepath.Match 规则
- <目标路径> 只有一个,可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。
FROM centos:7 WORKDIR /usr COPY aa.txt bb.txt /apps/ #复制两个文件到绝对路径/apps下8.ADD
ADD 指令和 COPY 的格式和性质基本一致,也是用来给镜像复制文件。但是在 COPY 基础上增加了一些功能。
- <源路径> 可以是一个 URL:在这情况下,Docker 引擎会试图去下载这个链接的文件放到 <目标路径> 去,下载后的文件权限自动设置为 600 。但下载文件不会自动解压缩。
- <源路径> 为一个 tar 压缩文件:ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。
FROM centos:7 WORKDIR /usr #从URL下载 ADD https://xxx.tar.gz /data/apps/ #本地解压文件 ADD tomcat-8.5.tar.gz /data/apps/ RUN mv tomcat-8.5 tomcat #改名



