• Dockerfile命令详解


    什么是 Dockerfile?

    Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。Docker读取Dockerfile文件里面的指令,自动地构建镜像。

    基本特点

    • dockerfile由许多行命令语句组成,支持以#开头为注释行
    • 行命令本身不区分大小写,但是一般把指令写成大写,用于区分命令行参数
    • Docker运行Dockerfile的指令是顺序执行的,因此在写Dockerfile文件的时候,一定要注意行命令的依赖关系,注意顺序
    • 第一个非注释的命令,必须从FROM开始

    基本结构

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

    dockerfile分为四部分:基础镜像信息、维护者信息、镜像操作指令、容器启动时执行指令,如:
    # This dockerfile user the ubuntu image
    # VERSION 2 - EDITON 1
    # Author: docker_user
    # Command format: Instruction [arguments / command] .. 
    # 第一行必须指定基于的基础镜像
    FROM ubuntu
    # 维护者信息
    MAINTAINER  docker_user docker_user@email.com 
    # 镜像的操作指令
    RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
    RUN apt-get update && apt-get install -y nginx 
    # 容器启动时执行指令
    CMD /usr/sbin/nginx
    

    Dockerfile常用指令  

    FROM 指令

    FROM指令是最重要的一个,且必须为Dockerfile文件开篇的第一个非注释行,用于为镜像文件构建过程指定基准镜像,后续的指令运行于此基准镜像所提供的运行环境,因此后续的命令行是否可以正常的使用,取决于该基准镜像。基准镜像可以是任何可用的镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry上,去所需的镜像文件。如果找不到指定的镜像文件,docker build会返回一个错误信息。

    语法格式:
    FROM <repository>[:<tag>]或者FROM <repository>@<digest镜像的hash码>
    <repository>:指定作为base image的名称
    <tag>:base image的标签,为可选项,省略时默认为latest

    MAINTAINER 指令
    用于让Dockerfile制作者提供本人的详细信息
    Dockerfile并不限制MAINTAINER指令出现的位置,但是推荐将其放置于FROM指令之后
    语法格式:
    MAINTAINER <discirbe message>
    discirbe message可是任何文本信息,但是约定俗成的使用作者名和邮件地址
    MAINTAINER "docker_user docker_user@email.com"

    LABEL指令
    用于为镜像添加元数据。一个镜像可以有多个LABEL指令,可以单行里指定多个标签。作者的信息,可以使用这个进行表示
    语法格式:
    LABEL <key>=<value> <key>=<value> <key>=<value> <key>=<value> ...

    COPY指令
    用于从Docker宿主机的当前目录复制文件到创建的新镜像中;
    语法格式:
    COPY <src>...<dest>或者 COPY ["<src>",... "<dest>"]
    <src>:要复制的源文件或者目录,支持使用通配符,src是相对路径
    <dest>:目标路径,即正在创建的images的文件系统路径;建议<dest>使用绝对路径,否则COPY指令使用以WORKDIR为其起始路径,在路径中有空白字符时,通常使用第二种格式
    文件复制准则:
    <src>必须是docker build时Dockerfile文件所在目录,上下文中的路径,不能是其父目录中的文件,
    如果<src>是目录,则其内部文件或者子目录会递归复制,但<src>目录自身不会被复制
    如果指定了多个<src>,或者<src>中使用了通配符,则<dest>必须是一个目录,且必须以/结尾
    如果<dest>事先不存在,它将会被自动创建,这包括其父目录路径

    ADD指令
    ADD指令类似于COPY指令,所不同的地方是ADD支持使用TAR文件和url路径
    语法格式:
    ADD <src>...<dest>或者 ADD ["<src>",... "<dest>"]
    操作准则:
    同COPY指令,将文件复制到镜像文件中,同样需求下,官方推荐使用 COPY
    如果<src>为url且<dest>不以/结尾,则<src>指定的文件将被下载并直接被创建为<dest>;如果<dest>以/结尾,则文件名url指定的文件将被直接下载并保存为<dest>/<filename>
    如果<src>是一个本地系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似于"tar -x"命令;然而,通过url获取到的tar文件将不会自动展开
    如果<src>有多个,或其间接或者直接使用了通配符,则<dest>必须是一个以/结尾的目录路径;如果<dest>不以/结尾,则其被视作一个普通文件,<src>的内容被直接写入到<dest>

    WORKDIR指令
    用于为Dockerfile中所有的RUN,CMD,ENTRYPOINT,COPY和ADD指令设定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。WORKDIR 指定的工作目录,必须是提前创建好的。
    docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。可以在 docker run命令中用 -w参数覆盖掉WORKDIR指令的设置。容器启动时执行的命令会在该目录下执行。
    相当于设置容器的工作目录了。在Dockerfile文件中,WORKDIR指令可出现多次,其路径也可以为相对路径。不过,其是相对此前一个WORKDIR指令指定的路径。另外,WORKDIR也可以调用由ENV指令定义的变量。
    语法格式:
    WORKDIR <dirpath>

    VOLUME指令
    用于在image中创建一个挂载点目录,以挂载docker host上的卷或者其他容器上的卷。而卷的创建,由docker daomen自动的在默认目录/var/lib/docker/volumes下创建卷,并挂载到这个挂载点。在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。
    如果挂载点目录路径下,有文件存在,docker run命令会在卷挂载完成后,将此前的所有文件赋值到新挂载的卷中。
    语法格式:
    VOLUME <mountpoint>或者VOLUME ["<mountpoint>"]

    EXPOSE指令
    声明运行时容器提供服务端口,容器打开指定要监听的端口,以实现与外部通信。这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。
    在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;
    另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。EXPOSE指令可一次指定多个端口,例如EXPOSE 11211/udp 11211/tcp
    语法格式:
    EXPOSE <port> [/<protocol>] [<port> [/<protocol>]...].<protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为tcp协议

    ENV指令
    用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其他指令(如ENV,ADD,COPY等)所调用。调用格式为$variable_name或者${variable_name}。
    可以在定义变量时为这些变量赋默认值,通过${variable:-默认值}方式,也可以在执行docker run命令时,为这些变量赋值,通过docker run --env 给变量赋值
    在dockerfile文件中定义的所有环境变量,可以在docker run启动容器后,在容器中使用,你可以通过pring env,查看这些定义的变量,
    在dockerfile中定义了这些变量,并赋值了,制作了镜像,在运行这个镜像的时候,可以通过docker run --env,为这些变量重新的赋值。
    语法格式:
    ENV <key>=<value> 或者 ENV <key>=<value> <key>=<value> ...
    第一种格式中,<key>之后的所有内容均会被视作其<value>的组成部分,因此,一次只能设置一个变量;
    第二种格式可一次设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<value>中包含空格,可以以反斜线()进行转义,也可以通过对<value>加双引号进行标识;
    另外,反斜线也可用于续行;定义多个变量时,建议使用第二种格式,以便在同一层中完成所有功能

    RUN指令
    用于指定docker build过程中,运行的程序,其可以是任何的命令。每条RUN 指令将在当前镜像基础上执行指定命令,将提交为新的镜像。当命令较长时可以使用 来换行
    语法格式:
    RUN <command>或者RUN ["<executable>","<param1>","<param2>"]
    第一种语法格式中,<command>通常是一个shell命令,且以"/bin/sh -c"来运行它,这意味着此进程在容器中的pid不为1,不能接受unix信号。因此,当使用docker stop <container>命令,停止容器时,
    此进程接受不到SIGTERM信号。而进到容器中查看pid的时候,又看到了其pid为1的信息,为什么呢?是因为docker 为了管理容器,在执行命令的时候,通过exec命令,把<command> 替换成原有进程的内容,沿用它的pid号。(因为任何在shell交互界面,执行的常用shell命令,都是通过fork一个子进程的方式来执行的)
    第二种语法格式中的参数是一个json格式的数组,其中<executable>为要运行的命令,后面的<paramN>为传递给命令的选项或者参数;然而,此种格式指定的命令,不会以"/bin/sh -c"来发起,
    因此常见的shell操作如变量替换以及通配符等替换将不会进程(即该程序由内核来直接启动,不经过shell fork的子进程,其pid直接为1,可以接受系统发出的signal信号);不过,如果要运行的命令依赖于此shell特性的话,可以将其替换为类似下面的格式。RUN ["/bin/bash","-c ","<executable>","<param1>"]。
    简单一句话就是,使用 exec 模式时,容器中的任务进程就是容器内的 1 号进程,特点是不会通过 shell 执行相关的命令,所以像 $HOME 这样的环境变量是取不到的;
    使用 shell 模式时,docker 会以 /bin/sh -c "task command" 的方式执行任务命令。也就是说容器中的 1 号进程不是任务进程而是 bash 的子进程。

    CMD指令
    类似于RUN指令,CMD指令也可用于运行任何命令或者应用程序。不过,二者的运行时间点不同。RUN指令运行于docker build镜像文件构建过程中,而CMD指令运行于基于Dockerfile文件构建出来的
    新镜像文件启动一个新容器时;CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过,CMD指定的命令,可以被docker run的命令行所覆盖;
    在Dockfile文件中,可以存在多个CMD指令,但仅最后一个CMD命令会生效。docker run指令命令行,就运行其指定的命令行,如果没有,就运行CMD指定的命令
    语法格式:
    CMD <command> 或者CMD ["<executable>","<param1>","<param2>"] 或者CMD ["<param1>","<param2>"]
    前两种语法格式的意义通RUN,第三种则用于为ENTRYPOINT指令提供默认参数

    ENTRYPOINT指令
    类似CMD指令的功能,用于为容器指定默认运行的程序,从而使得容器像是一个单独的可执行程序。与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当做参数传递给ENTRYPOINT指令指定的程序,不过,docker run命令的--entrypoint选项的参数可覆盖ENTRYPOINT指令指定的程序。docker run命令传入的命令参数会覆盖
    CMD指令的内容并且附加到ENTRYPOINT命令最后做为其参数使用。如果ENTRYPOINT和CMD同时存在,并且执行docker run的时候,没有指定命令行,那么CMD指定的内容,做为参数放到ENTRYPOINT后面。
    Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效。
    语法格式:
    ENTRYPOINT <command>(shell 中执行)或者 ENTRYPOINT ["<executable>","<param1>","<param2>"]

    USER指令
    用于指定运行image时或者运行Dockerfile中的任何RUN/CMD/ENTRYPOINT指令指定的程序时的用户和用户组。默认情况下,container的运行身份为root用户。
    语法格式:
    USER <UID>|<UserName>或者 USER <用户名>[:<用户组>]
    需要注意的是,用户和用户组必须提前已经存在,<UID>可以为任意数字,但是其必须为/etc/passwd中某用户的有效UID,否则docker run命令将运行失败

    HEALTHCHECK指令
    用于告诉docker怎样去检测一个容器,它还是处于工作状态的。比如有时候一个提供web服务的容器,虽然进程处于运行状态,但是它已经不能对外提供服务,不能处理新的web请求。
    语法格式:
    HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
    可选项包括:
    --interval(默认为30s)执行健康检测命令的周期间隔,
    --timeout(默认为30s) 执行健康检测命令后,认为失败的默认超时时间,
    --start-period(默认为0s) 有时候,主进程初始化需要一段时间,这个参数表示多长时间以后,开始第一次检测
    --retries(默认为3次),认为检测失败的次数
    CMD的退出状态表示了容器的监控状态。
    状态码为0,表示容器运行正常,且对外服务正常
    状态码为1,表示容器工作不正常
    状态码为2,未用
    HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
    样例:HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1

    ARG指令
    构建参数,与 ENV 作用一至。不过作用域不一样。ARG 定义的变量仅对 Dockerfile内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。
    构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖默认值。用户指定了一个Dockerfile文件中,未定义的参数,那么构建镜像时,会输出告警信息。Dockerfile文件中可以包括多个
    ARG指令
    语法格式:
    ARG <参数名>[=<默认值>]

    ONBUILD
    用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。
    当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这是执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。
    语法格式:
    ONBUILD <其它指令>

  • 相关阅读:
    web网站的测试需考虑的问题
    颜色搭配
    30岁前不必在乎的30件事情
    数据库时代的终结
    实现IT创业的十三种模式分析
    Linux rpm 命令参数使用详解[介绍和应用]
    PHP中的正则表达式及模式匹配
    linux下使用yum安装Apache+php+Mysql+phpMyAdmin
    jQuery.extend函数详细用法
    PHP CURL HTTP 研究笔记
  • 原文地址:https://www.cnblogs.com/potato-chip/p/14344944.html
Copyright © 2020-2023  润新知