zoukankan      html  css  js  c++  java
  • 10.Docker File制作镜像

    Docker File构建镜像

    https://docs.docker.com/engine/reference/builder/

    关于DockerFile

    在Docker中创建镜像最常用的方式,就是使用Dockerfile。Dockerfile是一个Docker镜像的描述文件,我们可以理解成火箭发射的A、B、C、D…的步骤。Dockerfile其内部包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

    640?wx_fmt=jpeg

    Dockerfile结构大致分为四个部分:

    1. 基础镜像信息
    2. 维护者信息
    3. 镜像操作指令
    4. 容器启动时执行指令

    Dockerfile每行支持一条指令,每条指令可带多个参数,支持使用以#号开头的注释。下面会对上面使用到的一些常用指令做一些介绍。

    Dockerfile常用指令

    指令 对象 含义
    FROM 镜像 指定新镜像所基于的镜像,必须为第一条指令
    MAINTAINER 名字 新镜像的维护人信息
    RUN 命令 在所基于的镜像上执行命令,并提交到新镜像中
    EXPOSE 端口号 指定新镜像加载到Docker时开启的端口号
    ENV 环境变量 变量值 设置一个环境变量的值,会被后面的RUN使用
    ADD 源文件/目录 目标文件/目录 将源文件复制到目标文件,源文件要与Docker位于同一目录下,或者为一个URL
    COPY 源文件/目录 目标文件/目录 将本地主机上的源文件/目录复制到目标地点,源文件/目录要与Dockerfile在同一目录下
    VOLUME ["目录"] 在容器中创建一个挂载点
    USER 用户名 /UID 指定运行容器时的用户
    WORKDIR 路径 为后续的RUN、CMD、ENTRYPOINT指定工作目录
    ONBUILD 命令 指定所生成的镜像作为一个基础镜像时所要运行的命令
    CMD ["要运行的程序","参数1","参数2"] 指定启动容器时运行的命令或脚本,只能有一条CMD命令,多条时只有最后一条被执行

    来一张通俗易懂的全景图:

    img

    FROM

    指明构建的新镜像是来自于哪个基础镜像

    FROM <repository>[:<tag>]
    #较为安全
    FROM <repository>@<digest>
    #<repository>:指定作为base image的名称
    #<tag>:base image的标签,为可选性,省略时默认为latest
    #<digest>:哈希码
    

    例如:

    FROM centos:7
    

    MAINTAINER(depreacted)

    指明镜像维护着及其联系方式(一般是邮箱地址),已被LABEL所替代

    MAINTAINER<author's detail>
    

    例如:

    MAINTAINER "MiaosenG <MiaosenG@MiaosenG.com>"
    

    不过,MAINTAINER并不推荐使用,更推荐使用LABEL来指定镜像作者,例如:

    LABEL maintainer="MiaosenG <MiaosenG@MiaosenG.com>"
    

    RUN

    #第一种格式<command>通常是一个shell命令,且以"/bin/sh -c"运行
    #此进程在容器的PID不为1,当使用docker stop <container>命令停止容器时,此进程接收不到SIGTERM信号
    RUN <command>
    #第二种格式中的参数是一个JSON格式数组,其中<executable>为要运行命令,<paramN>为传递命令选项或参数
    RUN ["<executable>","<param1>","<param2>"]
    #此格式不会以"/bin/sh -c"运行,无法使用变量替换或通配符等shell操作符,可写成
    RUN ["/bin/sh" "-c","<exrcutable>","<param1>"]
    

    构建镜像时运行的Shell命令,针对于基础镜像,仅可使用基础镜像环境,和命令;
    容器构建时,会启动临时容器执行 run命令;执行完成后生成镜像
    例如:

    RUN ["yum", "install", "httpd"]
    RUN yum install httpd
    

    jason数组中,要是用双引号

    CMD

    #意义等同RUN
    CMD <command>
    CMD ["<executable>","<param1>","<param2>"]
    #第三种用于ENTRYPOINT指令提供默认参数
    CMD ["<param1>","<param2>"]
    

    启动容器时执行的Shell命令,针对镜像默认运行命令,多个CMD仅最后一个生效

    例如:

    CMD ["-C", "/start.sh"] 
    CMD ["/usr/sbin/sshd", "-D"] 
    CMD /usr/sbin/sshd -D
    

    EXPOSE

    EXPOSE <port>[/<protocol>][ <port>[/<protocol>]...]
    #<protocol>用于指定传输层协议,可为tcp或udp,默认为TCP
    

    声明容器运行的(待暴露)默认服务端口,但运行容器时不会暴露该端口;需要配合docker run -P命令,会暴露DockerFile内写定的全部端口

    例如:

    EXPOSE 11211/udp 11211/tcp
    

    ENV

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

    设置环境内环境变量,可被文件中位于其后的其他指令所调用

    例如:

    #单一变量赋值
    ENV MYSQL_ROOT_PASSWORD 123456
    #多变量赋值
    ENV JAVA_HOME=/usr/local/jdk1.8.0_45
    
    #使用
    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 /usr/local/src/
    

    第一种格式,<key>之后所有内容均被视为<value>

    第二种格式,<value>中包含空格,可以利用进行转义或换行,也可以加""进行表示

    可配合docker run -e设定变量值使用,在初始化运行容器时改变默认设定变量

    ADD

    拷贝文件或目录到镜像中,例如:

    ADD <src>...<dest>
    ADD ["<src>"..."<dest>"]
    

    支持URL路径,用法同COPY

    #展开文件
    ADD nginx-1.15.2.tar.gz /usr/local/src/
    #仅下载不解压
    ADD http://nginx.org/download/nginx-1.15.2.tar.gz /usr/local/src/
    

    如果<src>为URL

    • <dest>不以/结尾,则<src>指定的文件将被下载并直接被创建为<dest>;
    • <dest>以/结尾,则文件名URL指定的文件将被直接下载并保存为<dest>/<filename>

    如果<src>是一个

    • 本地系统上的压缩格式的tar文件;他将会被展开为一个目录,类似于tar -x
    • URL获取的tar文件;将不会被展开

    如果<src>为多个,或期间使用了通配符,则<dest>必须是一个以/的目录路径;

    如果不以/结尾,则其被视作一个普通文件,<src>的内容将被直接写入到<dest>

    COPY

    拷贝主机文件或目录到镜像中

    COPY <src>...<dest>
    COPY ["<src>"..."<dest>"]
    #<src>:需要复制的源文件,支持通配符
    #<dest>:目标路径;建议使用绝对路径;否则,COPY指定则以WORKDIR为其其实路径
    

    用法同ADD,只是不支持自动下载和解压,例如:

    COPY index.html /data/web/html
    COPY yum.repos.d /etc/yum.repos.d
    

    <src>必须是build上下文中的路径,不能是其父目录中的文件

    如果<src>是目录,则其内部文件或子目录会被递归复制,但<src>目录自身不会被复制

    如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且必须以/结尾

    如果<dest>实现不存在,他将会被自动创建,这包括其父目录路径

    ENTRYPOINT

    ENTRYPOINT <command>
    ENTRYPOINT ["<executable>","<param1>","<param2>"]
    

    启动容器时执行的Shell命令,同CMD类似,只是由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序,例如:

    ENTRYPOINT ["/bin/bash", "-C", "/start.sh"]
    ENTRYPOINT /bin/bash -C '/start.sh'
    

    PS:Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效。

    除非使用docker run --entrypoint string才可强制覆盖dockerfile内有ENTRYPOINT命令

    当CMD与ENTRYPOINT同时出现在Dockerfile中;CMD使用第三种写法,为ENTRYPOINT指令提供默认参数

    CMD ["/bin/httpd","-f","-h","/data/web/html"]
    ENTRYPOINT ["/bin/sh","-c"]
    

    但当使用docker run对容器内部传参或输入指令,会对CMD进行覆盖,而不会覆盖ENTRYPOINT

    VOLUME

    VOLUME <mountpoint>
    VOLUME ["<mountpoint>"]
    

    指定容器挂载点到宿主机自动生成的目录或其他容器

    例如:

    VOLUME ["/data/mysql/"]
    

    PS:一般不会在Dockerfile中用到,更常见的还是在docker run的时候指定-v数据卷。

    USER

    USER <UID>|<UserName>
    

    为RUN、CMD和ENTRYPOINT执行Shell命令指定运行用户,默认容器中使用root用户

    例如:

    USER <user>[:<usergroup>]
    USER <UID>[:<UID>]
    USER miaoseng
    

    UID可以为任意数字,但实践中其必须为/etc/passwd(容器)中某用户的有效UID,否则docker run命令将失败

    WORKDIR

    WORKDIR <dirpath>
    

    为RUN、CMD、ENTRYPOINT以及COPY和AND设置工作目录,理解为cd命令

    例如:

    WORKDIR /usr/local/src/
    ADD nginx-1.15.2.tar.gz ./
    #等效于
    ADD nginx-1.15.2.tar.gz /usr/local/src/
    

    HEALTHCHECK

    HEALTHCHECK [options] CMD command
    

    告诉Docker如何测试容器以检查它是否仍在工作,即健康检查,例如:

    HEALTHCHECK --interval=5m --timeout=3s --retries=3 
        CMD curl -f http:/localhost/ || exit 1
    

    其中,一些选项的说明:

    • --interval=DURATION (default: 30s):每隔多长时间探测一次,默认30秒
    • -- timeout= DURATION (default: 30s):服务响应超时时长,默认30秒
    • --start-period= DURATION (default: 0s):服务启动多久后开始探测,默认0秒
    • --retries=N (default: 3):认为检测失败几次为宕机,默认3次

      一些返回值的说明:

    • 0:容器成功是健康的,随时可以使用
    • 1:不健康的容器无法正常工作
    • 2:保留不使用此退出代码

    SHELL

    修改shell类型

    #Linux
    SHELL ["/bin/sh","-c"]
    #Windows
    SHELL ["cmd","/S","/C"]
    

    STOPSIGNAL

    定义停止信号

    STOPSIGNAL signal
    

    ARG

    AGE <name>[=<default value>]
    

    在构建镜像时,指定一些参数,例如:

    FROM centos:7
    ARG author="MiaosenG <miaosen@MiaosenG.com>"
    LABEL maintainer="${author}"
    

    这时,我们在docker build时可以带上自定义参数user了,如下所示:

    docker build --build-arg author=Tony Dockerfile .
    

    ONBUILD

    ONBUILD <INSTRUCTION>
    

    用于在Dockerfile中定义一个触发器,延迟触发;当其他用户,基于含有ONBUILD镜像构建新镜像,再次构建并运行build时执行命令;留下后门

    ONBUILD不可自我嵌套,且不会触发FROM和MAINTAINER指令;通常使用RUN和ADD,使用ADD,COPY时可能缺少指定文件;无法拷贝

    CMD与RUN区别

    指令 CMD RUN
    区别 基于Dockerfile构建出新映像文件启动一个容器时 运行于映像文件构建过程中
    可被docker run命令选项进行覆盖,针对镜像默认运行命令 使用基础镜像环境,和命令
    可存在多个CMD仅最后一个生效 可运行多个

    例如:

    Dockerfile1

    vim Dockerfile
    FROM busybox
    LABEL maintainer="MiaosenG <miaoseng@miaoseng.com>" app="http"
    
    ENV WEB_DOC_ROOT="/data/web/html/"
    
    RUN mkdir -p $ENV WEB_DOC_ROOT && echo '<h1>hello busybox httpd server</h1>' > $ENV WEB_DOC_ROOT/indec.html
    
    CMD /bin/httpd -f -h ${WEB_DOC_ROOT}
    

    运行后查看容器内PID=1进程为/bin/httpd -f -h /data/web/html/

    Dockerfile2

    vim Dockerfile
    FROM busybox
    LABEL maintainer="MiaosenG <miaoseng@miaoseng.com>" app="http"
    
    ENV WEB_DOC_ROOT="/data/web/html/"
    
    RUN mkdir -p $ENV WEB_DOC_ROOT && echo '<h1>hello busybox httpd server</h1>' > $ENV WEB_DOC_ROOT/indec.html
    
    CMD ["/bin/httpd","-f","-h","${WEB_DOC_ROOT}"]
    

    运行后报错httpd:can't change directory to '${WEB_DOC_ROOT}': No such file or directory

  • 相关阅读:
    BZOJ 3514 Codechef MARCH14 GERALD07加强版
    WT
    Codeforces 348
    POI 2010
    Codeforces 336
    MVC实例及用三层架构实现对学生信息的增删改查
    欠拟合和过拟合
    线性回归案例
    梯度下降法介绍
    线性回归的损失函数和梯度下降
  • 原文地址:https://www.cnblogs.com/Gmiaomiao/p/13203749.html
Copyright © 2011-2022 走看看