六、Dockerfile构建镜像

1、介绍

使用Dockerfile这种方式是将制作镜像的操作全部写入到一个文件中,而docker build 命令可以读取这个文件中的所有操作,并根据这些配置创建相应的镜像。

 

2、Dockerfile 中的内容主要以两种形式出现

注释行和指令行:

①注释行

以#开头的文本均为注释行,可以在其中写上我们对Dockerfile 的解释,以及每行指令代表的意义。

②指令行

  • 行首 INSTRUCTION
  • 指令所接收的参数 arguments

注意:指令是不区分大小写的,也就是说,可以使用小写形式的指令,但为了更清晰地分辨指令和参数,指令一般采用大写形式。

 

3、指令解析行

在Dockerfile 中, 并非所有以#开头的行都是注释行,有一类特殊的参数是通过以#开头的行来指定的,这类行的基本形式是:

# directive=value

此类行称为解析指令行( Parser Directives ),它的主要作用是提供一些解析Dockerfile需要使用的参数。

 

4、具体的指令含义

I、基础指令

① FROM指令 即我们所要构建的镜像所基于的镜像,通常情况下我们会选择一个系统镜像来布置完整的应用,当然也可以通过基于其他己完成的应用镜像。

特点:

  • 必须在注释之外的第一行
  •  一个DockerFile可以包含多个From,但是每一个From作为镜像的分割,生成多个,不建议这样写,还是一个DockerFile一个From比较好。

格式:

  •  FROM <image>
  •  FROM <image>:<tag>
  •  FROM <image>@<digest>

 ②MAINTAINER指令  用处是提供镜像的作者信息

格式:

  • MAINTAINER <name>

 

II、控制指令

控制指令是Dockerfile 的核心部分,我们通过控制指令来描述整个镜像的构建过程。

①RUN指令  用来给定这些需要被执行的操作的。

特点:

  • 每一次执行RUN指令之后,就会创建一个新的镜像层。
  • RUN指令执行的时候是有缓存的,如果使用的指令一致,即使两次执行的结果不一致,也会返回原来的值,所以如果存在这样的事情,需要在docker build的是添加 --no-cache 参数。

格式: 这两种使用格式代表的意义不同,适用的场景也有区别。

  • RUN command param1 param2 .”
  • RUN [” executable ”,” param1 ”,”param2 ”,…]

第一种方式,是以shell中执行的方式,默认使用的是/bin/sh, 最大的优势在于支持换行书写,通过 \ 来进行换行,对应比较长的命令,可以使用这种方式, 通过Shell指令可以切换shell

第二种方式,是直接执行命令,可以有效规避在某些基础镜像中没有Shell 程序,或者用于需要临时切换Shell 程序的时候。

②WORKDIR

WORKDIR 指令用于切换构建过程中的工作目录,对于 RUN,CMD,COPY,ADD 指令将会在指定的工作目录中去执行。也可以理解为命令执行时的当前目录。

特点:

可以给出的是绝对目录,也可以给出的是相对目录,甚至可以使用环境变量

格式:

  •  WORKDIR /usr
  •  WORKDIR local

③ONBUILD

它可以携带另一条指令,但是不是在本次build的时候执行,而是在构建其他镜像并使用FROM 指令把当前的镜像作为基础镜像时执行。类似一个触发器。

特点:

  • ONBUILD 指令只会在构建子镜像中执行,当子镜像构建完成后,这些指令也随之消失,所以它们不会继承到子镜像或者更后辈的镜像中
  • 不允许 ONBUILD  ONBUILD  这样嵌套使用

格式:

  •  ONBUILD INSTRUCTION arguments

 

III、引入指令

希望将文件加入到即将构建的镜像中,引入指令就能够帮助我们实现这个目的。

①ADD指令

ADD指令可以将一些软件源码、配置文件、执行脚本等从外部导入到镜像的构建过程。

特点:

  • 设置导入文件<src>路径时,需要使用相对路径,这样才能保证移动Dockerfile和其目录后不需要再进行修改。
  • 所有被复制进镜像的文件都将放置到<dest>给出的目录下,这个目录可以是绝对路径,也可以是相对于镜像的工作目录而言的相对路径
  • ADD能添加网络文件,但是对于带认证的服务器不支持,能够支持自动的文件解压缩,自动解压文件只对本地文件有效,如果<src>给出的是网络路径, Docker 不会对文件进行解压。

格式:

  • ADD <src> ... <dest>
  • ADD ["<src>”,...”<dest>”]

②COPY指令

特点

  • 和ADD主要的区别就在于COPY 指令不能识别网络地址,也不会自动对压缩文件进行解压

格式:

  • COPY <src> ... <dest>
  • COPY ["<src>”,...”<dest>”]

 

IV.执行指令

执行指令能够指定通过镜像建立容器时,容器默认执行的命令。我们通常使用这些命令来启动镜像中的主要程序。

①CMD

特点:

  •  因为容器中只会绑定一个应用程序,所以在Dockerfile 中只存在一个CMD 指令,如果我们给出了多个CMD 指令,之后的指令会覆盖掉之前的指令。
  •  可以在启动容器的时候,通过手动输入的方式来覆盖DockerFile当中的CMD 

格式:

  • CMD ["executable”,”paraml”,”param2 ”,..]
  • CMD [”paraml”,”param2", ... ]
  • CMD command paraml param2 ... 

第一种和第二种和RUN指令类似,对于第三种这种格式则是将给出的参数传给ENTRYPOINT指令给出的程序。

备注:

不要混淆了CMD 指令和RUN 指令,它们的区别是很大的。

RUN 指令是在镜像构建的过程中执行,并将执行结果提交到新的镜像层中;

CMD 指令在镜像构建的过程中不能执行,它只是配直镜像的默认入口程序。

 

V.ENTRYPOINT

启动主程序之前可能会涉及到其他程序的启动和运行,那么使用CMD可以做到,但是把主程序启动和其他程序启动都杂糅到一起,会显得比较混乱。

ENTRYPOINT 指令就是专门用于主程序启动前的准备工作的。

特点:

如果使用了ENTRYPOINT指令,CMD 指令的值会被当作 ENTRYPOINT 指令的参数附加到 ENTRYPOINT 指令的后面,并且如果 docker run 中指定了参数,会覆盖 CMD 中给出的参数。

举个例子:

FROM ubuntu:latest ENTRYPOINT ["ls", "-a"] CMD ["-l"]

如果执行 docker run <image>  相当于执行 docker run <image> ls -a -l (ENTRYPOINT  + CMD )

如果执行 docker run <image> -i -s 相当于执行  docker run <image>  ls -a -i -s (ENTRYPOINT  + CMD被覆盖 )

应该避免在使用ENTRYPOINT 时把CMD 指令的形式配置成shell 格式,即CMD command paraml param2 ...。因为如果这样做,在ENTRYPOINT 里是以次级命令的方式,启动CMD 的Shell 进程的,所以这个进程在容器中的PID 井不是1, Docker 就不会把容器的生命周期绑定到这个进程上。这就会使我们在外部对容器发出的信号无法发送到这个进程上,包括容器停止时发出的信号,而没有收到信号的程序会被强制结束,这就会造成数据的损坏以及其他意想不到的结果。

格式:

使用ENTRYPOINT 指令的方式与使用CMD 指令的方式非常相似。

  • ENTRYPOINT [”executable”,”paraml", "param2"]
  • ENTRYPOINT command param1 param2 …

 

VI.配置指令

 

①EXPOSE (开放端口但不是实际映射)

如果容器中的应用程序需要让其他镜像访问到它提供的端口,需要显式给出对外提供的端口号。而没有给出的端口号,即使容器中的应用程序对它们进行了监听,但Docker 没有对它们进行转接,所以在容器外依然是访问不到的。

格式:

  • EXPOSE <port> [<port> .. . ]

注意

EXPOSE 指定在容器运行时监听指定的网络端口,它与 docker run 命令的 -p 参数不一样,并不实际映射端口,只是将该端口暴露出来,允许外部或其它的容器进行访问。

要将容器端口暴露出来,需要在 dcoker run 命令中使用 -p 或者 --publish 参数。如果采用 -P 随机映射端口的方式,Docker 会将在 DockerFile 中声明的所有 EXPOSE 的端口随机映射。

 

②ENV

ENV 指令用于设置环境变量

特点:

  • 环境变量也是能够继承的,所有在基础镜像中设置的环境变量,也都会被继承到将要构建的镜像中。
  • 我们可以通过docker inspect 命令查看镜像中的环境变量,在容器创建时也可以通过一env 参数来新增和替换环境变量: docker run --env <key>=<value>

格式:

  •  ENV <key> <value>
  •  ENV <key>=<value> <key>=<value>...

 

③LABEL

使用LABEL 指令,可以为即将生成的镜像提供一些元数据作为标记,这些标记能够帮助我们更好地展示镜像的信息。

格式:LABEL <key>=<value> <key>=<value> <key>=<value>

 

④USER

USER 指令用于设置执行用户,我们可以传入用户的名称或UID作为USER 指令的参数。

特点:在Dockerfile 中可以指定一个用户,后续的 RUN,CMD 以及 ENTRYPOINT 指令都会使用该用户去执行,但是该用户必须提前存在。

格式:USER nginx

 

⑤ARG

ARG主要是用于设置变量的。

特点:

  • 和ENV指令不同的是,它不会作用于继承该镜像的镜像,而只会在该镜像Build的时候生效。也可以在docker build的时候通过--build-arg 来进行指定。
  • 如果ARG定义的变量和ENV重复,那么ENV 指令所定义的变量永远都会覆盖ARG 指令所定义的变量即可,即使它们定义的顺序是相反的。

格式:

  • ARG <name>
  • ARG <name>=<default>

ARG定义是变量,如果不设置默认值,需要从外部传入,举例:

FROM busybox ARG user USER $user

在build的时候,可以传入这个user变量的值

docker build --build-arg user=root ./busybox

 

⑥STOPSIGNAL

当我们停止容器时, Docker会向容器中的应用程序传递停止信号,我们可以通过STOPSIGNAL 指令来修改Docker 所传递的信号。

STOPSIGNAL 支持两种格式定义的信号, 一种是用Linux 内核syscall 信号的数字表示,另一种是用信号的名称表示。

格式:

  • STOPSIGNAL 9
  • STOPSIGNAL  Kill

⑦SHELL

CMD 、ENTRYPOINT 等指令都支持以shell 形式执行,而SHELL指令可以为它们选定Shell 程序。SHELL 指令的使用格式如下:

  • SHELL [” executable”,”parameters”]

举例:Docker 默认使用的Shell 程序是/bin/sh ,若要改为/bin/bash ,可以使用如下SHELL指令:

  • SHELL ["/bin/bash","-C"]

 

posted @ 2020-03-12 17:07  奋斗的大橙子  阅读(306)  评论(0编辑  收藏  举报