Dockerfile功能以及其工作流程

    docker可以通过阅读dockerfile文件自动建立镜像,dockerfile是一个文本文档型的,所有用户能在命令行进行的操作命令都可以在此定义,从而将这些命令组合起来,并生成一个直接可用的镜像。使用“docker build”,用户可以连续执行多个指令,从而实现构建的自动化。本文将会介绍在dockerfile中可以执行的命令参数。

    docker build命令可以从一个dockerfile或者一个文本构建镜像,构建文本可以是一个本地路径或者是一个GIT的URL路径。"docker build ."表示使用当前目录作为上下文进行构建(警告,不要在根目录执行此命令,这将会把你的硬盘的上下文信息全部传送到docker进程当中,自己想想后果吧),默认情况下,如果不使用-f选项指定,会加载名为Dockerfiler的文件。然后可以使用-t选项指定构建镜像的tag标签以及仓库名称,例如(可以添加多个参数):

        docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .

    docker的构建操作是由docker守护进程完成的,而非CLI(命令行操作)。其构建顺序是,首先把上下文信息发送到进程,然后docker守护进程将会依次执行Dockerfile里面的指令到新的镜像当中,并且会在结束后自动清除上下文信息。为了提升Docker性能,还可以在上下文目录添加一个".dockerignore"文件。需要注意的是,Dockerfile中的每一条指令都是完全独立的,也就是说你不能指望通过"RUN cd /tmp"指令,将下一条指令的工作环境设置到"/tmp"目录下面。

    docker会尽量使用镜像缓存(默认),从而提高其工作性能。当然,也可以通过"--no-cache=true"不使用缓存构建。构建完成后,就可以通过push指令上传到指定注册中心的仓库了。

Dockerfile写作风格:

    一,基本语法

    # Comment 

    INSTRUCTION arguments

    "INSTRUCTION"是不区分大小写的,但是为了区分起见,以大写为好。Dockerfile每一行仅支持一条指令,Dockerfile的起始位置的第一个非注释行需要使用"FROM"指令指定构建使用的来源镜像,指令区域的起始最好有以"#"的注释行,以说明当前区域执行的任务内容。

    二,变量置换

  • 在dockerfile中,变量声明可以表示为$variable_name或者${variable_name},主要是用来区别没有空格的变量,例如${foo}_bar。

  • dockerfile中的变量声明也支持少量的bash修饰符,例如:

    • ${variable_name:+word}:    如果已经赋值且非空,则使用$variable_name的值,如果没有,则返回空字符串

    • ${variable_name:-word}:    如果已经赋值,则使用$variable_name的值,如果没有,使用word

  • word可以为任意字符串,包含附加的环境变量

  • 也可以使用"\"符号进行转义,例如"\$foo"表示内容就是"$foo"

  • 环境变量可以在以下指令中使用:

    • ADD|COPY|ENV|EXPOSE|LABEL|USER|WORKDIR|VOLUME|STOPSIGNAL

    • 也可以使用ONBUILD指令(需要docker版本大于1.4)

  • 环境变量支持替换

    三,dockerignore file

    在docker执行命令(发送上下文信息到进程之前)时,如果存在".dockerignore"文件,则其中定义的文件或目录不ADD或COPY指令添加到镜像当中。例如:

        */temp*    #如,/aa/template.txt

        */*/temp*    #如,/aa/bb/template.conf

        temp?    #如,/tempaa或/tempbb

        *.md

        !README.md    #取反,这两行结合使用,表示包含所有以.md结尾的,除了README.md以外的文件

    使用匹配格式都参照go语言风格

Dockerfile指令说明:

  • FROM

    • 作用:指令构建来源镜像,它必须处于第一个非注释指令

    • 语法:FROM <image> 或者 FROM <image>:<tag> 或者 FROM <image>@<digest>,后两个(标签和摘要)是可选的,如果无法匹配,则返回错误

  • MAINTAINER

    • 作用:指定生成镜像的作者

    • 语法:MAINTAIN <name>

  • RUN

    • 作用:在引用的的镜像中执行命令,并提交结果,用于dockerfile后面的操作

    • RUN指令的部分操作会存储在缓存当中,如果下次构建不使用"--no-cache=true",则有可能会出问题

    • 语法:RUN有两种写法

      • RUN <command>

      • RUN ["executable", "param1", "param2"]

    • 样例:

      • RUN /bin/bash -c "source $HOME/.bashrc ; echo $HOME" #跨行操作时可以添加反斜杠

      • RUN ["/bin/bash", "-c", "echo hello"]

    • 注意事项:RUN指令的部分操作会存储在缓存当中,如果下次构建不使用"--no-cache=true",则有可能会出问题

  • CMD

    • 作用:CMD的主要目的是为执行容器提供一些默认参数,这些设置可以包括一个可执行文件,或者一个系统命令。CMD指令只能在dockerfile中存在一次,如果有多条,则只执行最后一条

    • 语法:CMD有三种写法

      • CMD ["executable", "param1", "param2"]

      • CMD ["param1", "param2"] #此种写法需要配置ENTRYPOINT指令结合使用,如果两个都独立使用,则只会执行最后一个CMD或者ENTRYPOINT指令

      • CMD command param1 param2  #shell风格

  • LABEL

    • 作用:LABEL指令用来添加一些元数据到镜像当中,LABEL是键值对类型数据,一个镜像可以有一个或者多个标签,但是过多的标签则会导致生成一个低能的镜像。当指定多个标签时,尽量在一层显示,而不是使用多个LABEL指令指定。可以使用docker inspect查看镜像的LABEL信息

    • 语法:LABEL <key>=<value> <key>=<value> <key>=<value> <key>=<value> ……

  • EXPOSE

    • 作用:指定容器映射到主机的端口,Docker容器的IP是随机生成的,所以外部访问是需要通过主机端口映射访问的,而EXPOSE指定了其映射到主机的端口,具体可参考man docker-run中的-p或者-P选项

    • 语法:EXPOSE <port> [<port>...]

  • ENV

    • 作用:设置环境变量,此处的变量可以在dockerfile中引用 

    • 语法:ENV有两种写法

      • ENV <key> <value>

      • ENV <key>=<value> ....  #建议用此种写法,只产生一个ENV缓存层

  • ADD

    • 作用:ADD指令可以将源(可以是文件,目录或者URL)添加到容器里面的路径下,可以使用匹配规则添加文件。如果是个URL,则会将其下载到容器目标路径当中

    • 语法:ADD有两种写法

      • ADD <src> ... <dest>

      • ADD ["<src>",... <dest>]  #这种形式一般用于包含空格的路径

  • COPY

    • 语法:COPY有两种写法

      • COPY <src> ... <dest>

      • COPY ["<src>",... <dest>]  #这种形式一般用于包含空格的路径

    • 作用:COPY是将源文件或目录复制到容器内指定路径内,如果不携带dest参数,则会创建完整的缺失目录

  • ENTRYPOINT

    • 作用:该指令的使用分为两种情况,一种是自己单独使用,另一种是和CMD结合使用。结合使用时,ENTRYPOINT指令只能执行命令,但不能指定参数部分;CMD指令不是一个完整的可执行命令,而仅仅是参数部分。例如以下案例:

                        FROM ubuntu  
                        CMD ["-l"]  
                        ENTRYPOINT ["/usr/bin/ls"] 

    • 语法:ENTRYPOINT同样有两种语法

      • ENTRYPOINT ["executable", "param1", "param2"]

      • ENTRYPOINT command param1 param2

  • VOLUME

  • 作用:VOLUME指令可以创建一个挂载点给容器使用,从而实现容器内数据的持久化(容器在关闭后数据是会消失的)。卷可以通过docker create 来创建,也可以直接使用docker run创建,卷只能在没有容器连接时才能被删除,通过docker run 创建的卷是可以共享给其它容器使用的。例如(有关volume更多介绍,请参考链接:https://docs.docker.com/engine/userguide/containers/dockervolumes/#mount-a-host-directory-as-a-data-volume

  • 语法:VOLUME ['/data']

  • 参考样例:docker run -d -P --volume-driver=flocker -v my-named-volume:/opt/webapp --name web training/webapp python app.py


USER
  • 作用:用以指定用户名或者UID,当使用RUN、CMD和ENTRYPOINT指令的时候,会以此身份进行运行

  • 语法:USER daemon

WORKDIR
  • 作用:WORKDIR指令用以设定RUN、CMD和ENTRYPOINT指令的工作目录

  • 语法:WORKDIR /path/to/workdir

ARG
  • 作用:ARG指令定义了一个变量,这个变量可以接受docker build --build-arg <argname>=<value>的入参

  • 语法:ARG <name>[=<default value>]

  • 用例:

    • FROM images1

    • USER ${user:-some_user} 

    • ARG user 

    • USER $user

    • docker build --build-arg user=user_name Dockerfile

ONBUILD
  • 作用:ONBUILD指定的指令在构建镜像时并不会执行,只会在构建其子镜像时执行

  • 语法:ONBUILD [INSTRUCTION]

STOPSIGNAL
  • 作用:STOPSIGNAL用以设置退出状态码,可以是正常的系统信号,如SIGKILL,也可以是匹配的数字,主机可以通过这个信号关闭容器

  • 语法:STOPSIGNAL signa