0
点赞
收藏
分享

微信扫一扫

Docker第七篇(Dockerfile)

 简介

  Dockerfile是Docker用来构建镜像的文本文件,包含自定义的指令和格式。可以通过docker build命令从Dockerfile中构建镜像。这个过程与传统分布式集群的编排配置过程相似,且提供了一系列统一的资源配置语法。用户可以用这些统一的语法命令来根据需求进行配置,通过这份统一的配置文件,在不同的平台上进行分发,需要使用时就可以根据配置文件自动化构建同时,Dockerfile与镜像配合使用,使Docker在构建时可以充分利用镜像的功能进行缓存,大大提升了Docker的使用效率。

示例 

   首先我们可以去docker官网上下载一个centos7.4的景象,想在地址是:​​https://hub.docker.com/​​  

  Docker第七篇(Dockerfile)_centos

  这里说一下,如果我们去docker官网或者自建的仓库中下载镜像的时候,一定要加上tag,也就是标签,如果不加默认是latest(最新版)。

  Docker第七篇(Dockerfile)_docker_02

  我们下载一下上面的centos7.4的镜像,发现这个镜像的tag就是dadoha/centos7.4.1708:latest,冒号前面标注了下载地址,冒号后面标注了下载的版本,有人说7.4.1708不就是版本么,怎么还有个latest呢。你可以理解为每个版本的镜像里面的改动地方不同,所以一般都会再标注一个小版本。

  Docker第七篇(Dockerfile)_环境变量_03

  Docker第七篇(Dockerfile)_docker_04

简单的Dockerfile

cd /root/docker
mkdir /root/docker
touch Dockerfile

  Docker第七篇(Dockerfile)_docker_05

   上面我们已经创建了一个简单的Dockerfile文件,From是告诉docker这个镜像的基础镜像是dadoha/centos7.4.1708(前面我们已经下载过了,所以它会从本地查找,如果本地没有就会从官网直接下载),具体的命令都是做什么用的,后面我们再详细介绍。下面是创建镜像的命令,-t指的是新镜像的标签,后面的路径是Dockerfile的存放路径,这里可以写绝对路径,也可以写相对路径。

  Docker第七篇(Dockerfile)_docker_06

   新的镜像已经生成,不过还有地方需要补充,后面我们再了解。

  Docker第七篇(Dockerfile)_环境变量_07

Dockerfile指令   

  简介

  Dockerfile的基本格式如下:INSTRUCTION arguments

​   在Dockerfile中,指令(INSTRUCTION)不区分大小写,但是为了与参数区分,推荐大写。Docker会顺序执行Dockerfile中的指令,第一条指令必须是FROM指令,它用于指定构建镜像的基础镜像。​​ 

   在Dockerfile中以#开头的行是注释,而在其他位置出现的#会被当成参数。

         Dockerfile中的指令有FROM、MAINTAINER、RUN、CMD、EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、ONBUILD,错误的指令会被忽略。

         Dockerfile 分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。

基础镜像信息   # FROM    
维护者信息 # MAINTAINER
镜像操作指令 # RUN、COPY、ADD、EXPOSE等
容器启动时执行指令 #CMD、ENTRYPOINT

    基础镜像是需要说明我们这个新的镜像是要以哪个镜像作为基础,维护者信息这里一般会标明作者和作用,镜像指令说明在这个镜像里面要执行哪些命令,安装软件、建文件和文件夹等等系统操作,容器启动时执行指令这里需要注意一下,如果我们安装的是服务,比如说tomcat、nginx,zabbix,这里要写的就是启动这些服务,如果是操作系统这里也要写一个一直在执行的指令,我们叫守护进程,否则它执行完以后就直接退出了。

  详细说明

    ENV

       格式:ENV <key> <value>或ENV <key>=<value>,前者一般是在设置一个环境变量时候使用,后者是可以同时设置多个。中间用空格隔开,例如key1=path2 key2=path2

       ENV指令可以为镜像创建出来的容器生命环境变量。并且在Dockerfile中,ENV指令声明的环境变量会被后面的特定指令(即ENV、ADD、COPY、WORKDIR、EXPOSE、VOLUME、USER)解释使用。其他指令使用环境变量时,使用格式为$variable_name或者${variable_name}。在变量前面添加斜杠\可以转义,如\$foo或者\${foo},将会被分别转换为$foo和${foo},而不是环境变量所保存的值。另外,ONBUILD指令不支持环境替换。 

     FROM

       格式:FROM <image> 或FROM <image>:<tag>

      FROM指令的功能是为后面的指令提供基础镜像,因此一个有效的Dockerfile必须以FROM指令作为第一条非注释指令。从公共镜像库中拉取镜像很容器,基础镜像可以选择任何有效的镜像。在一个Dockerfile中,FROM指令可以出现多次,这样会构建多个镜像。在每个镜像创建完成后,Docker命令行界面会输出该镜像的ID。若FROM指令中参数tag为空,则tag默认是latest;若参数image或tag指定的镜像不存在,则返回错误。

     COPY

      格式:COPY <src> <dest>

            COPY指令复制<src>所指向的文件或目录,将它添加到新镜像中,复制的文件或目录在镜像中的路径是<dest>。<src>所指定的源可以有多个,但必须在上下文中,即必须是上下文根目录的相对路径。不能使用形如COPY ../something  /something这样的指令。此外,<src>可以使用通配符指向所有匹配通配符的文件或目录,例如,COPY hom* /mydir/ 表示添加所有以“hom”开头的文件到目录/mydir/中。

           <dest>可以使文件或目录,但必须是目标镜像中的绝对路径或者相对于WORKDIR的相对路径(WORKDIR即Dockerfile中WORKDIR指令指定的路径,用来为其他指令设置工作目录)。若<dest>以反斜杠/结尾则其指向的是目录;否则指向文件。<src>同理。若<dest>是一个文件,则<src>的内容会被写入到<dest>中;否则<src>所指向的文件或目录中的内容会被复制添加到<dest>目录中。当<src>指定多个源时,<dest>必须是目录。另外,如果<dest>不存在,则路径中不存在的目录会被创建。

     ADD

      格式:ADD <src> <dest>

            ADD与COPY指令在功能上很相似,都支持复制本地文件到镜像的功能,但ADD指令还支持其他功能。<src>可以是一个指向一个网络文件的URL,此时若<dest>指向一个目录,则URL必须是完全路径,这样可以获得该网络文件的文件名filename,该文件会被复制添加到<dest>/<filename>。例如,ADD http:example.com/foobar   /会创建文件/foobar。

            <src>还可以指向一个本地压缩归档文件,该文件在复制到容器中时会被解压提取,如ADD example.tar.xz /。但若URL中的文件为归档文件则不会被解压提取。

    RUN

           ADD和COPY指令虽然功能相似,当一般推荐使用COPY,因为COPY只支持本地文件,相比ADD而言,它更透明。

      RUN指令有两种格式:    

      ​​RUN <commadn> (shell格式)​​​​      ​​​​RUN ["executable","param1","param2" ](exec格式,推荐格式)​

       RUN指令会在前一条命名创建出的镜像的基础上创建一个容器,并在容器中运行命令,在命令结束运行后提交容器为新镜像,新镜像被Dockerfile中的下一条指令使用。

            RUN指令的两种格式表示命令在容器中的两种运行方式。当使用shell格式时,命令通过/bin/sh -c运行;当使用exec格式时,命令是直接运行的,容器不调用shell程序,即容器中没有shell程序。exec格式中的参数会当成JSON数据被Docker解析,故必须使用双引号而不能使用单引号。因为exec格式不会再shell中执行,所以环境变量的参数不会被替换,例如,当执行CMD ["echo","$HOME"]指令时,$HOME不会做变量替换。如果希望运行shell程序,指令可以写成CMD["shell","-c",“echo",“$HOME”]

       示例:

      多个命令之间用&&隔开,换行用/即可。这里一定要注意一个dockerfile里面用一个RUN最佳,因为多个RUN会形成多层镜像。

      Docker第七篇(Dockerfile)_环境变量_08

     CMD     

      功能为容器启动时要运行的命令

      语法有三种写法

1. CMD ["executable","param1","param2"]
        2. CMD ["param1","param2"]
        3. CMD command param1 param2

         第三种比较好理解了,就时shell这种执行方式和写法

         第一种和第二种其实都是可执行文件加上参数的形式

         举例说明两种写法:

CMD [ "sh", "-c", "echo $HOME" ]
CMD [ "echo", "$HOME" ]

       补充细节:这里边包括参数的一定要用双引号,就是",不能是单引号。千万不能写成单引号。

       原因是参数传递后,docker解析的是一个JSON array

       RUN & CMD

      不要把RUN和CMD搞混了。

      RUN是构件容器时就运行的命令以及提交运行结果

      CMD是容器启动时执行的命令,在构件时并不运行,构件时紧紧指定了这个命令到底是个什么样子

    ENTRYPOINT

      ENTRYPOINT指令有两种格式:   

ENTRYPOINT <command>  (shell格式)
        ENTRYPOINT ["executable","param1","param2"] (exec格式,推荐格式)

      ENTRYPOINT和CMD很像,他两可以如果一起用执行不同的命令的话,谁在最后面就谁生效,当前前者就不再执行了。还有一种用法如下:

      CMD ["-l"]

      ENTRYPOINT ["/usr/bin/ls"]

      这种用法简直就是变态,直接CMD ["/usr/bin/ls","-l"]或者CMD ls -l,但就是有这中用法,很尴尬。

    USER

      USER:指定运行容器时的用户名或 UID,后续的操作都会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户

格式:
  USER user
  USER user:group
  USER uid
  USER uid:gid
  USER user:gid
  USER uid:group

示例:
  USER www

注:
  使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。

    WORKDIR    

​      为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录。可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径,示例:​

      WORKDIR /root

      WORKDIR test

      RUN vim 1.txt

      等同于:

      RUN cd /root/test/ && vim 1.txt

    ARG

      ARG是Docker1.9 版本才新加入的指令。格式:ARG<name>[=<default value>]

         ARG指定了一个变量在docker build的时候使用,可以使用--build-arg <varname>=<value>来指定参数的值,不过如果构建的时候不指定就会报错。

    LABEL

      LABEL执行是向镜像中添加元数据,一个LABEL是一个键值对,在LABEL的值中使用添加空格,使用双引号和反斜线。示例:

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."

      示例:

      ​​LABEL multi.label1="value1" \​​​​       multi.label2=​​​​"value2" \​​​​      other="value3"​

      查看镜像的LABEL可以使用docker inspect命令:

"Labels": {    
"com.example.vendor": "ACME Incorporated"
"com.example.label-with-value": "foo",
"version": "1.0",
"description": "This text illustrates that label-values can span multiple lines.",
"multi.label1": "value1",
"multi.label2": "value2", "
other": "value3"
},

    VOLUME

      格式:VOLUME ["/data"]或者直接VOLUME /data

          可以将本地文件夹或者其他container的文件夹挂载到container中,注意这里说的是管理卷,生成的镜像不管在哪里运行,都会将本地的/data目录挂载到容器中。

    EXPOSE

      功能为暴漏容器运行时的监听端口给外部,但是EXPOSE并不会使容器访问主机的端口,如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上 -p参数,例如-p 80:80,意义为将后者(容器的80端口)映射到前者(宿主机的80)端口上。


附加:

  1、修改镜像标签

  docker tag    原名称:版本   新名称:版本

  例如:docker tag testcentos7.4.01:latest  testcentos7:latest





举报

相关推荐

0 条评论