• DockerFile


    一般来说,通用的Docker image没法满足公司的业务需求,需要根据公司的实际需求制作特定image,方法主要有两个:
    1.基于容器创建
    2. DockerFile

    DockerFile Format

    1. # 注释
    2. INSTRUCTION 参数 (INSCTRUCTION最好用大写)
    3. 顺序执行INSTRUCTION
    4. 第一个非注释行的INSTRUCTION必须以FROM开始,去指定基础image
    5. 必须以一个专用目录,Dockerfile文件必须存在,首字母必须大写,引用文件的路径必须是专用目录为开始,也可以用子目录来包含所有文件,一定不能是父目录。也可以用.dockerignore来指定文件路径,打包时所有在此文件中指定的文件都不包含,类似黑名单,起文件排除的作用。
    6. 制作image的指令是docker build,docker build会隐式启动一个容器,同时在Dockerfile中能执行的命令必须是基础image中包含的。
    7. 可以用环境变量Environment variables,Dockerfile中的变量和shell的变量非常类似
        ${variable:-word}:indicates that if variable is set then the result will be that value. If variable is not set then word will be the result.
        ${variable:+word} :indicates that if variable is set then word will be the result, otherwise the result is the empty string.
    

    DockerFile INSTRUCTION

    FROM

    1:定义
    指令是最重的一个且必须为Dockerfile文件开篇的第一个非注释行,用于为映像文件构建过程指定基准镜像,后续的指令运行于此基准镜像所提供的运行环境。实践中,基准镜像可以是任何可用镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry或指定的Registry上拉取所需的镜像文件。
    2:语法
        • FROM <repository>[:<tag>] 或
        • FROM <resository>@<digest>
            • <reposotiry>:指定作为base image的名称;
            • <tag>:base image的标签,为可选项,省略时默认为latest;
    

    LABEL

    1.:定义
        用于让Dockerfile制作者提供本人的详细信息
        Dockerfile并不限制LABEL指令可在出现的位置,但推荐将其放置于FROM指令之后
    2:语法
        - LABEL <key>=<value> <key>=<value> <key>=<value>
        - LABEL 是键值类型
        - 一个image可以有多个label
        - 可以在一行中指定多个label
    

    COPY

    1:定义
        用于从Docker主机复制文件至创建的新映像文件
    2:语法
        - COPY <src> ... <dest> 或
        - COPY ["<src>",... "<dest>"]
            • <src>:要复制的源文件或目录,支持使用通配符
            • <dest>:目标路径,即正在创建的image的文件系统路径;建议为<dest>使用绝对路径,否则,COPY指定则以WORKDIR为其起始路径;
    3:文件复制准则
        - <src>必须是build上下文中的路径,不能是其父目录中的文件
        - 如果<src>是目录,则其内部文件或子目录会被递归复制,但<src>目录自身不会被复制
        - 如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且必须以结尾
        - 如果<dest>事先不存在,它将会被自动创建,这包括其父目录路径
    4:实例
        # vim Dockerfile
            #Description: test image
            FROM busybox
            LABEL maintainer="Evan <liangjindong0@qq.com>" app="httpd"
            COPY index.html /data/web/html/
        # 当前目录下,创建index.html: echo hello > index.html
        # docker build -t tinyhttpd:v0.1-1 ./
        # docker run --name tinyweb1 --rm tinyhttpd:v0.1-1 cat /data/web/html/index.html
        # cp -r /etc/yum.repos.d/ ./
        # vim Dockerfile
            #Description: test image
            FROM busybox
            LABEL maintainer="Evan <liangjindong0@qq.com>" app="httpd"
            COPY index.html /data/web/html/
            COPY yum.repos.d /etc/yum.repos.d/ (会把yum.repos.d下的所有文件copy到/etc/yum.repos.d/目录下,必须以/结尾)
        # docker build -t tinyhttpd:v0.1-2 ./
        # docker run --name tinyweb1 --rm tinyhttpd:v0.1-2 ls /etc/yum.repos.d/
    

    ADD

    1:定义
        ADD指令类似于COPY指令,ADD支持使用TAR文件和URL路径
    2:语法
        • ADD <src> ... <dest> 或
        • ADD ["<src>",... "<dest>"]
    3:操作准则
        - 同COPY指令
        - 如果<src>为URL且<dest>不以/结尾,则<src>指定的文件将被下载并直接被创建为<dest>;如果<dest>以/结尾,则文件名URL指定的文件将被直接下载并保存为<dest>/<filename>
        - 如果<src>是一个本地系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似于“tar -x”命令;然而,通过URL获取到的tar文件将不会自动展开;
        - 如果<src>有多个,或其间接或直接使用了通配符,则<dest>必须是一个以/结尾的目录路径;如果<dest>不以/结尾,则其被视作一个普通文件,<src>的内容将被直接写入到<dest>;
    4:实例
        # vim Dockerfile
            ADD http://nginx.org/download/nginx-1.15.2.tar.gz /usr/local/src/
        # docker build -t tinyhttpd:v0.1-3 ./
        # docker run --name tinyweb1 --rm tinyhttpd:v0.1-3 ls /usr/local/src/  (只会上传,不会解压)
        # 如果nginx-1.15.2.tar.gz是本地文件,会在目标上解压
    

    WORKDIR

    1:定义
          用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD指定设定工作目录
    2: 语法
    WORKDIR <dirpath>
        • 在Dockerfile文件中,WORKDIR指令可出现多次,其路径也可以为相对路径,不过,其是相对此前一个WORKDIR指令指定的路径
        • 另外,WORKDIR也可调用由ENV指定定义的变量
    例如
        • WORKDIR /var/log
        • WORKDIR $STATEPATH
    

    VOLUME

    1: 定义
        用于在image中创建一个挂载点目录,以挂载Docker host上的卷或其它容器上的卷
    2:语法
        • VOLUME <mountpoint> 或
        • VOLUME ["<mountpoint>"]
        如果挂载点目录路径下此前在文件存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中
    3:实例
        # vim Dockerfile
            VOLUME /data/mysql/
            此volume是docker自动管理的类型
        # docker build -t tinyhttpd:v0.1-4 ./
        # docker run --name tinyweb1 --rm tinyhttpd:v0.1-4 sleep 60
        # docker inspect tinyweb1
    

    EXPOSE

    1:定义
        用于为容器打开指定要监听的端口以实现与外部通信
    2:语法
        EXPOSE <port>[/<protocol>] [<port>[/<protocol>] ...]
            • <protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议
            • EXPOSE指令可一次指定多个端口,例如
                EXPOSE 11211/udp 11211/tcp (只是可以暴露,需要在docker run -P才会暴露在Dockerfile中定义的EXPOSE端口)
    3:实例
    # vim Dockerfile
        EXPOSE 80/tcp
    # docker build -t tinyhttpd:v0.1-5 ./
    # docker run --name tinyweb1 --rm tinyhttpd:v0.1-5 /bin/httpd -h /data/web/html
        只可以访问Docker IP的网页
    # docker run --name tinyweb1 --rm -P tinyhttpd:v0.1-5 /bin/httpd -h /data/web/html
    # docker port tinyweb1
        可以访问Docker宿主机IP的网页
    

    ENV

    1:定义
        用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其它指令(如ENV、ADD、COPY等)所调用,调用格式为$variable_name或${variable_name}
    2:语法
        • ENV <key> <value> 或
        • ENV <key>=<value> ...
        • 第一种格式中,<key>之后的所有内容均会被视作其<value>的组成部分,因此,一次只能设置一个变量
        • 第二种格式可用一次设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<value>中包含空格,可以以反斜线()进行转义,也可通过对<value>加引号进行标识;另外,反斜线也可用于续行
        • 定义多个变量时,建议使用第二种方式,以便在同一层中完成所有功能
    3:实例
        # vim Dockerfile
            ENV DOC_ROOT=/data/web/html/ 
                    WEB_SERVER_PACKAGE="nginx-1.15.2"
            COPY index.html ${DOC_ROOT:-/data/web/html/}
            ADD ${WEB_SERVER_PACKAGE}.tar.gz ./src/
        # image构建和启动是两个不同的过程,两个不同的阶段,Dockerfile中定义的EVN在启动时会注入到容器中
        # docker build -t tinyhttpd:v0.1-6 ./
        # docker run --name tinyweb1 --rm -e WEB_SERVER_PACKAGE="nginx-1.15.1" tinyhttpd:v0.1-6 printenv
    

    RUN

    1:定义
        用于指定docker build过程中运行的程序,其可以是任何命令
    2:语法
        • RUN <command> 或
        • RUN ["<executable>", "<param1>", "<param2>"]
        • 第一种格式中,<command>通常是一个shell命令,且以“/bin/sh -c”来运行它,这意味着此进程在容器中的PID不为1,不能接收Unix信号,因此,当使用docker stop container>命令停止容器时,此进程接收不到SIGTERM信号;
        • 第二种语法格式中的参数是一个JSON格式的数组,其中<executable>为要运行的命令,后面的<paramN>为传递给命令的选项或参数;然而,此种格式指定的命令不会“/bin/sh -c”来发起,以内核发起,不支持shell操作符如管道,重定向等。因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行;不过,如果要运行的命令依赖于此shell特性的话,可以将其替换为类似下面的格式。
                RUN ["/bin/bash", "-c", "<executable>", "<param1>"]
        • 注意:JSON数组中,要使用双引号
    3:实例
    # vim Dockerfile
        RUN    yum makecache &&
                    yum install nginx -y && 
                    yum clean all
    # 
    

    CMD

    1:定义
        类似于RUN指令,CMD指令也可用于运行任何命令或应用程序,不过,二者的运行时间点不同
            • RUN指令运行于映像文件构建过程中,而CMD指令运行于基于Dockerfile构建出的新映像文件启动一个容器时
            • CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过,CMD指定的命令其可以被docker run的命令行选项所覆盖
            • 在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效
    2:语法
        • CMD <command> 或
        • CMD [“<executable>”, “<param1>”, “<param2>”] 或
        • CMD ["<param1>","<param2>"]
        • 前两种语法格式的意义同RUN
        • 第三种则用于为ENTRYPOINT指令提供默认参数
    3:实例
        - 第一种格式:以shell启动
    
        # vim Dockerfile
            FROM busybox
            LABEL maintainer="Evan <liangjindong0@qq.com>" app="httpd"
    
            ENV WEB_DOC_ROOT="/data/web/html/"
            RUN mkdir -p ${WEB_DOC_ROOT} && 
            echo '<h1>Busybox httpd server.</h1>' > ${WEB_DOC_ROOT}/index.html
    
            CMD /bin/httpd -f -h ${WEB_DOC_ROOT}
        # docker build -t tinyhttpd:v0.1-7 ./
        # docker run --name tinyweb1 --rm -it tinyhttpd:v0.1-7 ()
        # docker ps (启动为/bin/sh的子进程)
             "/bin/sh -c '/bin/ht…" 
        #  docker exec -it tinyweb1 /bin/sh (shell中exec COMMAND,exec取代shell为1的进程,shell退出)
             / # ps
                PID   USER     TIME  COMMAND
                1 root      0:00 /bin/httpd -f -h /data/web/html/ ()
                6 root      0:00 /bin/sh
               11 root      0:00 ps
        - 第二种格式:不是以shell启动,可以指定用shell
        # vim Dockerfile
            CMD ["/bin/httpd","-f","-h ${WEB_DOC_ROOT}"]
        # docker build -t tinyhttpd:v0.1-8 ./
        # docker run --name tinyweb1 --rm -it tinyhttpd:v0.1-8 
            httpd: can't change directory to ' ${WEB_DOC_ROOT}': No such file or directory (不是以shell启动,所以无法识别${WEB_DOC_ROOT}'变量)
        指定用shell启动
        # vim Dockerfile
            CMD ["/bin/sh","-c","/bin/httpd","-f","-h ${WEB_DOC_ROOT}"]
        # docker build -t tinyhttpd:v0.1-9 ./
        
        - 第三种格式: 带ENTRYPOINT
           # vim Dockerfile
            CMD ["/bin/httpd","-f","-h ${WEB_DOC_ROOT}"]
            ENTRYPOINT /bin/sh
            (CMD的命令会作为ENTRYPOINT的参数传递)
            #  docker run --name tinyweb1 --rm -it tinyhttpd:v1.4
            # docker inspect tinyweb1
                "Cmd": [
                "/bin/httpd",
                "-f",
                "-h ${WEB_DOC_ROOT}"
                ],
            "ArgsEscaped": true,
            "Image": "tinyhttpd:v1.4",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "/bin/sh",
                "-c",
                "/bin/sh"
                ],
            解释:用/bin/sh -c运行/bin/sh
    
            ENTRYPOINT ["/bin/sh","-c"]
             "Cmd": [
                "/bin/httpd",
                "-f",
                "-h ${WEB_DOC_ROOT}"
            ],
            "ArgsEscaped": true,
            "Image": "sha256:ba8350e53c013997d443f1f5ee68083a906b76a35e771fe89cf9426947ebc015",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "/bin/sh",
                "-c"
            ],
    
        # docker run --name tinyweb1 --rm -it tinyhttpd:v1.6 "ls /data" (能执行,CMD作为默认参数时传给ENTRYPOINT,但是docker run运行时传的参数会传给ENTRYPOINT,ls命令作为shell的子进程运行,此时docker run传的参数覆盖的是CMD参数)
    

    注意:RUN基于基础image中的命令;RUN可以运行多次,同样属性的命令用一行描述
                docker run中CMD只能有一个
                运行的时间点不同,运行的行为不同
    

    ENTRYPOINT

    1:定义
        • 类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序
        • 与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序
        • 另外,docker run命令的--entrypoint选项的参数可覆盖ENTRYPOINT指令指定的程序
    2:语法
            • ENTRYPOINT <command>
            • ENTRYPOINT ["<executable>", "<param1>", "<param2>"]
            • docker run命令传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令最后做为其参数使用
            • Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效
    3:实例
        # vim DockerfileENTRYPOINT /bin/httpd -f -h ${WEB_DOC_ROOT}
        # docker run --name tinyweb1 --rm -it tinyhttpd:v1.3
        # docker run --name tinyweb1 --rm -it tinyhttpd:v1.3 ls /data/web/html (ls /data/web/html不会覆盖ENTRYPOINT定义的)
        # docker run --name tinyweb1 --rm -it --entrypoint "ls /data/web/html" tinyhttpd:v1.3 (可以用--entrypoint来强制覆盖)
    4:应用场景
       多数情况下,ENTRYPOINT是用来指定一个shell,作为用来启动别的进程的父进程,docker run的命令行参数会作为它的子进程来运行,达到灵活传递参数并且被shell解析
        空器接授变量需要通过环境变量
    5:实例(Nginx接授变量生成配置文件,而且变量可以在启动容器时传递)
        # vim entrypoint.sh
            #!/bin/sh
            #
            cat > /etc/nginx/conf.d/www.conf << EOF
            server {
            server_name ${HOSTNAME};
            listen ${IP:-0.0.0.0}:${PORT:-80};
            root ${NGX_DOC_ROOT:-/user/share/nginx/html};
            }
            EOF
            exec "$@"
        # chmod +x entrypoint.sh
        # vim Dockerfile
            FROM nginx:1.14-alpine
            LABEL maintainer="Evan <liangjindong0@qq.com"
            ENV NGX_DOC_ROOT="/data/web/html/"
            ADD entrypoint.sh /bin/
            CMD ["/usr/sbin/nginx","-g","daemon off;"] (前台运行Nginx)
            ENTRYPOINT  ["/bin/entrypoint.sh"] (首先用此脚本会以shell运行初始化一个配置文件,然后运行CMD,顶替entrypoint.sh,即Nginx进行运行后,shell脚本退出,Nginx成为容器中的唯一进程,而且是主进程)
        # docker run --name tinyweb1 --rm -P -e "PORT=8080" -h Apache tinyhttpd:v1.8
        # docker run --name tinyweb1 --rm -p 80:80  -h Apache tinyhttpd:v1.8
        # docker exec -it tinyweb1 /bin/sh
        # / # netstat -tnl (port参数被docker run启动时指定参数8080成功)
            tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN
            tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
        # / # ps
            PID   USER     TIME   COMMAND
            1 root       0:00 nginx: master process /usr/sbin/nginx -g daemon off; (Nginx能以PID为1的主进程运行,是因为entrypoint.sh脚本中的exec "$@")
            8 nginx      0:00 nginx: worker process
            9 root       0:00 /bin/sh
            总结:ENTRYPOINT脚本来定义参数,在创建image时传入值,在docker run时接收参数来启动容器
  • 相关阅读:
    Django基础篇
    转 枚举设备栈
    转 Windows串口过滤驱动程序的开发
    VS2010 + WinDDK 搭建驱动开发环境(转)
    cef 下载地址
    electron入门教程
    转:PHP 生成复杂JSON格式 简单快速方法
    CEF General Usage(CEF3预览)
    转:关于使用ImageMagick和Tesseract进行简单数字图像识别
    转 Tesseract-OCR 字符识别---样本训练
  • 原文地址:https://www.cnblogs.com/liangjindong/p/9409697.html
Copyright © 2020-2023  润新知