Dockerfile

 
3、Dockerfile 
 
dockerfile 是一个文本格式的配置文件, 用户可使用 Dockerfile 来快速建立自定义的镜像。
镜像的定制实际上就是定制每一层所添加的配置、文件。若是咱们能够把每一层修改、安装、构建、操做的命令都写入一个脚本,用这个脚原本构建、定制镜像,那么以前说起的没法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。
所谓定制镜像,那必定是以一个镜像为基础,在其上进行定制。
 

 
指令:
 
包括 “配置指令" (配置镜像信息)和 “操做指令" (具体执行操做)
 
配置指令:
 
ARG (定义建立镜像过程当中使用的变量)
格式:ARG <参数名>[=<默认值>]
构建参数和 ENV 的效果同样,都是设置环境变量。所不一样的是,ARG 所设置的构建环境的环境变量,在未来容器运行时是不会存在这些环境变量的。
Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值能够在构建命令 docker build 中用  --build-arg <参数名>=<值> 来覆盖。
 
 
FROM:(指定所建立镜像的基础镜像,必备)*
格式:FROM <镜像> [AS <别名>]
必须是第一条指令,若是一个Dockerfile中建立多个镜像时,可使用多个FROM指令(每一个镜像一次)。
除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为 scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。
若是你以 scratch 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将做为镜像第一层开始存在。
 
 
LABEL:(添加镜像元数据标签信息)
格式:LABEL <键>=<值> <键>=<值> ...
如:LABEL author="xxx"  date="xxx"
 
 
EXPOSE(声明镜像内服务监听的端口)
格式: EXPOSE <端口1> [<端口2>/<协议>...]
EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会由于这个声明应用就会开启这个端口的服务(即不会自动完成端口映射)。
在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另外一个用处则是在运行时使用随机端口映射时,也就是 docker run -P(大写) 时,会自动随机映射 EXPOSE 的端口。
要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。-p,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。
 
 
ENV(设置环境变量)
格式有两种:
  • ENV <key> <value>
  • ENV <key1>=<value1> <key2>=<value2>...
不管是后面的其它指令,如 RUN,仍是运行时的应用,均可以直接使用这里定义的环境变量。在镜像启动的容器中也会存在。指令指定的环境变量在运行时能够被覆盖掉, 如 docker run --env <key>=<value> built_image 。
注意当一条 ENV 指令中同时为多个环境变量赋值而且值也是从环境变量读取时, 会为变量都赋值后再更新。
如:
ENV NODE_VERSION 7.2.0
RUN curl -SLO " https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz"
下列指令能够支持环境变量展开: ADD、COPY、ENV、EXPOSE、LABEL、USER、WORKDIR、VOLUME、STOPSIGNAL、ONBUILD。
 
 
ENTRYPOINT(指定镜像的默认入口命令)
格式有两种:
  • ENTRYPOINT ["executable", "param1", "param2"]  exec调用执行;
  • ENTRYPOINT command param1 param2    shell中执行;
ENTRYPOINT 的目的和 CMD 同样,都是在指定容器启动程序及参数。
该入口命令令会在启动容器时做为根命令执行, 全部传人值做为该命令的参数。
每一个 Dockerfile 中只能有一个 ENTRYPOINT, 当指定多个时, 只有最后一个起效。
在运行时, 能够被 --entrypoint 参数覆盖掉, 如 docker run --entrypoint。
 
 
VOLUME(建立一个数据卷挂载点)
格式为:
  • VOLUME ["<路径1>", "<路径2>"...]
  • VOLUME <路径>
对于数据库类须要保存动态数据的应用,其数据库文件应该保存于卷中, 为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,咱们能够事先指定某些目录挂载为匿名卷,这样在运行时若是用户不指定挂载,其应用也能够正常运行,不会向容器存储层写入大量数据。
 
 
USER(指定运行容器时的用户名或UID)
格式:USER <用户名>[:<用户组>]
USER 指令和 WORKDIR 类似,都是改变环境状态并影响之后的层。WORKDIR 是改变工做目录,USER 则是改变以后层的执行 RUN, CMD 以及 ENTRYPOINT 这类命令的身份。
这个用户必须是事先创建好的,不然没法切换。
要临时获取管理员权限可使用 gosu 命令
 
 
WORKDIR (为后续的RUN、CMD、ENTRYPOINT 指定配置工做目录)
格式: WORKDIR <工做目录路径>
能够来指定工做目录(或者称为当前目录),之后各层的当前目录就被改成指定的目录,如该目录不存在,WORKDIR 会帮你创建目录。
可使用多个 WORKDIR 指令,后续命令若是参数是相对路径, 则会基于以前命令指定的路径(合并路径) 。为了不出错,推荐 WORKDIR 指令中只使用绝对路径。
 
 
ONBUILD(指定当基于所生成镜像建立子镜像时,自动执行的操做指令)
格式:ONBUILD <其它指令>
ONBUILD 是一个特殊的指令,它后面跟的是其它指令, 而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。
Dockerfile 中的其它指令都是为了定制当前镜像而准备的,惟有 ONBUILD 是为了帮助别人定制本身而准备的。
 
 
HEALTHCHECK(配置所启动容器如何进行健康检查)
格式:
  • HEALTHCHECK [选项] CMD <命令>:设置检查容器健康情况的命令
  • HEALTHCHECK NONE:若是基础镜像有健康检查指令,使用这行能够屏蔽掉其健康检查指令
HEALTHCHECK 指令是告诉 Docker 应该如何进行判断容器的状态是否正常。
 
 
STOPSIGNAL(指定所建立镜像启动的容器接收退出的信号值)
STOPSIGNAL signal
 
 
SHELL(指定其余命令使用 shell 时的默认 shell 类型)
SHELL ["executable", "parameters"]
默认值为 ["/bin/sh","-c"]
对于 windows 系统, Shell 路径中使用了“\”做为分隔符,建议在 Dockerfile 开头添- 加# escap= ' 来指定转义符
 
 
操做指令:
 
RUN(运行指定命令)
 
其格式有两种:
一、shell 格式: RUN <命令>,就像直接在命令行中输入的命令同样。
二、exec 格式: RUN ["可执行文件", "参数1", "参数2"],这更像是函数调用中的格式。
每个 RUN 的行为,就和手工创建镜像的过程同样:新创建一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像。
Dockerfile 中每个指令都会创建一层,每个 RUN 都是启动一个容器、执行命令、而后提交存储层文件变动。
镜像是多层存储,每一层的东西并不会在下一层被删除,会一直跟随着镜像。 镜像构建时,必定要确保每一层只添加真正须要添加的东西,任何无关的东西都应该清理掉。
Union FS 是有最大层数限制的,好比 AUFS,曾经是最大不得超过 42 层,如今是不得超过 127 层。
Dockerfile 支持 Shell 类的行尾添加 \ 的命令换行方式,以及行首 # 进行注释的格式。
 
 
CMD(指定启动容器时默认执行的命令)
CMD 指令的格式和 RUN 类似
格式:
  • shell 格式:CMD <命令>
  • exec 格式:CMD ["可执行文件", "参数1", "参数2"...]
  • CMD ["参数1", "参数2"...] 提供给 ENTRYPOINT的默认参数
在指令格式上,通常推荐使用 exec 格式,这类格式在解析时会被解析为 JSON 数组,所以必定要使用双引号 ",而不要使用单引号。
每一个 Dockerfile 只能有一条 CMD 命令,若是指定了多条命令,只有最后一条会被执行。
若是用户启动容器时候手动指定了运行的命令(做为 run 命令的参数),则会覆盖掉CMD 指定的命令。
Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,须要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的。
Docker 不是虚拟机,容器中的应用都应该之前台执行,而不是像虚拟机、物理机里面那样,用 systemd 去启动后台服务,容器内没有后台服务的概念。
 
 
ADD(添加内容到镜像,更高级的复制文件)
格式: ADD  <源路径>  <目标路径> 
ADD 指令和 COPY 的格式和性质基本一致。可是在 COPY 基础上增长了一些功能。
 <源路径> 能够是 Dockerfile 所在目录的一个相对路径(文件或目录);也能够是一个URL ;还能够是一个 tar 文件。若是 <源路径> 为一个 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的状况下,ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。
 
原则: 尽量的使用 COPY, 最适合使用 ADD 的场合,就是所说起的须要自动解压缩的场合。
 
 
COPY(复制内容到镜像)
格式:
  • COPY [--chown=<user>:<group>] <源路径>... <目标路径>
  • COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
<源路径> 能够是多个,甚至能够是通配符,其通配符规则要知足 Go 的  filepath.Match 规则,且指的是上下文(context) 目录下的路径,所以 COPY 这类指令中的源文件的路径都是相对路径。
COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。
<目标路径> 能够是容器内的绝对路径,也能够是相对于工做目录的相对路径(工做目录能够用 WORKDIR 指令来指定)。目标路径不须要事先建立,若是目录不存在会在复制文件前先行建立缺失目录。
使用 COPY 指令,源文件的各类元数据都会保留。好比读、写、执行权限、文件变动时间等。
 

 
建立镜像
 
基本的格式: docker build [OPTIONS]  PATH |URL | -
 
该命令将读取指定路径下(包括子目录)的 Dockerfile ,并将该路径下全部数据做为上下文( Context )发送给 Docker 服务端 Docker 服务端在校验 Dockerfile 格式经过后,逐条执行其中定义的指令,碰到 ADD 、COPY、 RUN 指令会生成一层新的镜像。 最终若是建立镜像成功,会返回最终镜像的 ID。要指定生成镜像的标签信息,能够经过 -t 选项
 
docker build 的工做原理:
 
Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为  Docker Remote API,而如 docker 命令这样的客户端工具,则是经过这组 API 与 Docker 引擎交互,从而完成各类功能。
 
虽然表面上咱们好像是在本机执行各类 docker 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也由于这种 C/S 设计,让咱们操做远程服务器的 Docker 引擎变得垂手可得。
 
docker build 命令构建镜像,其实并不是在本地构建,而是在服务端,也就是 Docker 引擎中构建的。 当构建的时候,用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的全部内容打包,而后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会得到构建镜像所需的一切文件。
 
在默认状况下,若是不额外指定 Dockerfile 的话,会将上下文目录下的名为 Dockerfile 的文件做为 Dockerfile。
实际上 Dockerfile 的文件名并不要求必须为 Dockerfile,并且并不要求必须位于上下文目录中,好比能够用 -f ../Dockerfile.php 参数指定某个文件做为 Dockerfile。
 
上下文的概念。当构建的时候,用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的全部内容打包,而后上传给 Docker 引擎(注意看上图第二行)。这样 Docker 引擎收到这个上下文包后,展开就会得到构建镜像所需的一切文件。 写一个 .dockerignore 用于剔除不须要做为上下文传递给 Docker 引擎的。
相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息