zoukankan      html  css  js  c++  java
  • docker instructions命令及dockerfile实践

    Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。有了 Dockerfile,当我们需要定制自己额外的需求时,只需在 Dockerfile 上添加或者修改指令,重新生成 image 即可,省去了敲命令的麻烦。
    基础镜像信息
    FROM      第一条指令必须为FROM指令,并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令(每个镜像一次)
    MAINTAINET 指定维护者的信息。
    Label    给构建的镜像打标签。
    镜像操作指令
    RUN     每条指令将在当前镜像基础上执行,并提交为新的镜像。(可以用“”换行)
    CMD     指定启动容器时执行的命令,每个Dockerfile只能有一条CMD指令,如果指定了多条指令,则最后一条执行。(会被启动时指定的命令覆盖)
    ADD     复制指定的到容器的中,可以是Dockerfile所在的目录的一个相对路径;可以是URL,也可以是tar.gz(自动解压)
    COPY    复制本地主机的( 为 Dockerfile 所在目录的相对路径)到容器中的(当使用本地目录为源目录时,推荐使用 COPY)
    WORKDIR 为后续的 RUN 、 CMD 、 ENTRYPOINT 指令配置工作目录。(可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径, 则会基于之前命令指定的路径)
    EXPOSE  告诉Docker服务端暴露端口,在容器启动时需要通过 -p 做端口映射
    VOLUME  创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等
    USER    指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。
    ONBUILD 配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令
    
    容器启动时执行指令
    ENV     指定环境变量,会被RUN指令使用,并在容器运行时保存
    ENTRYPOINT     配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。(每个 Dockerfile 中只能有一个 ENTRYPOINT ,当指定多个时,只有最后一个起效)

    实例
    FROM openjdk:8-jdk-alpine
    MAINTAINER Kurisu "makise_kurisuu@outlook.jp"
    LABEL maintainer="makise_kurisuu@outlook.jp"
    VOLUME /tmp
    ARG JAR_FILE=target/alice-server.jar
    COPY ${JAR_FILE} app.jar
    ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

    dockerfile命令详解

    FROM  构建的镜像设置基础镜像
    FROM <image> [AS <name>]
    FROM <image>[:<tag>] [AS <name>]
    FROM <image>[@<digest>] [AS <name>]
    FROM指令初始化新的构建阶段,并为后续指令设置基础镜像,FROM openjdk:8-jdk-alpine。因此,Dockerfile文件必须以FROM指令开头。 而指定的镜像可以使任何有效的镜像(推荐使用公共仓库的镜像,因为拉取更为容易)。

    在Dockerfile文件中ARG是唯一一个可以用于FROM之前的指令
    ARG CODE_VERSION=latest
    FROM base:${CODE_VERSION}
    CMD /code/run-app

    FROM extras:${CODE_VERSION}
    CMD /code/run-extras

      MAINTAINET  指定维护者的信息
      格式:MAINTAINET <name>

    LABLE  给构建的镜像打标签
    格式:LABEL <key>=<value> <key>=<value> <key>=<value> ...

    RUN 在镜像的构建过程中执行特定的命令,并生成一个中间镜像。比如安装一些软件、配置一些基础环境,可使用来换行。

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

    要注意的是,executable是命令,后面的param是参数
    采用exec格式指令将会被解析成json格式所以不能使用单引号,并且使用反斜杠也是必须要转移的,这在windows上尤为重要。

    CMD 指定容器运行时的默认参数

    CMD ["executable","param1","param2"](exec格式,首选)
    CMD ["param1","param2"](给ENTRYPOINT提供默认参数)
    CMD command param1 param2(shell格式)

    注意:RUN是在构建的时候执行,并生成一个新的镜像,CMD在构建时不进行任何操作,在容器运行的时候执行。
    如果CMD用于为ENTRYPOINT指令提供缺省参数,那么CMDENTRYPOINT指令都应该使用JSON数组格式。

    ADD 构建镜像时,复制上下文中的文件到镜像内。

    ADD <src>... <dest>
    ADD ["<src>",... "<dest>"](路径包含空格的必须使用这种格式)

    <src>可以是文件、目录,也可以是文件URL。可以使用模糊匹配(wildcards,类似shell的匹配),可以指定多个<src>,必须是在上下文目录和子目录中, 无法添加../a.txt这样的文件。如果<src>是个目录,则复制的是目录下的所有内容,但不包括该目录。如果<src>是个可被docker识别的压缩包, docker会以tar -x的方式解压后将内容复制到<desct><dest>可以是绝对路径,也可以是相对WORKDIR目录的相对路径。 所有文件的UID和GID都是0
     

    COPY 将主机的文件复制到镜像内,如果目的位置不存在,Docker会自动创建所有需要的目录结构,但是它只是单纯的复制,并不会去做文件提取和解压工作
    COPY <src>... <dest>
    COPY ["<src>",... "<dest>"](路径包含空格的必须使用这种格式)
    注意:需要复制的目录一定要放在Dockerfile文件的同级目录下。
    因为构建环境将会上传到Docker守护进程,而复制是在Docker守护进程中进行的。任何位于构建环境之外的东西都是不可用的。 COPY指令的目的的位置则必须是容器内部的一个绝对路径。

    WORKDIR 为接下来的Dockerfile指令指定当前工作目录,可多次使用,如果使用的是相对路径,则相对的是上一个工作目录,类似shell中的cd命令。
    WORKDIR /path/to/workdir
    受影响的指令有:RUN、CMD、ENTRYPOINT、COPY和ADD。 可以在Dockerfile中多次使用WORKDIR指令。如果提供了相对路径,则它将相对于上一个WORKDIR指令的路径。
    例如:
    WORKDIR /a
    WORKDIR b
    WORKDIR c
    RUN pwd
    此Dockerfile中pwd指令将输出 /a/b/c.。
    WORKDIR指令可以解析之前使用ENV设置的环境变量,只能使用Dockerfile中显式设置的环境变量。
    例如:
    ENV DIRPATH /path
    WORKDIR $DIRPATH/$DIRNAME
    RUN pwd
    此Dockerfile中pwd指令将输出 /path/$DIRNAME。

    EXPOSE 为构建的镜像设置监听端口。
    EXPOSE <port> [<port>/<protocol>...]
    EXPOSE指令让docker容器在运行的时候监听指定的端口,可以指定端口是upd还是tcp协议,如果没有指定则默认tcp协议。
    EXPOSE指令并不会发布端口,如果发布端口,则需要在docker run时使用-p来发布和映射一个或多个容器端口、或者使用-P来发布所有公开的端口
    并将它们映射到高阶端口。

    VOLUME 指定镜像内的目录为数据卷。
    VOLUME ["/data"]
    在容器运行的时候,docker会把镜像中的数据卷的内容复制到容器的数据卷中去。 如果在接下来的Dockerfile指令中,修改了数据卷中的内容,则修改无效。

    USER 为接下来的Dockerfile指令指定用户。受影响的指令有:RUN、CMD、ENTRYPOINT。
    USER <user>[:<group>] or
    USER <UID>[:<GID>]
    注意:当用户没有主要组时,镜像(或下一条指令)将与该root组一起运行

    ONBUILD 向镜像中添加一个触发器,当以该镜像为基础镜像再次构建新的镜像时,会触发执行其中的指令。
    ONBUILD [INSTRUCTION]
    比如我们生成的镜像是用来部署Python代码的,但是因为有多个项目可能会复用该镜像。你可以这样使用:
    [...]
    # 在下一次以此镜像为base image的构建中,执行ADD . /app/src,将项目代目添加到新镜像中去
    ONBUILD ADD . /app/src
    # 并且build Python代码
    ONBUILD RUN /usr/local/bin/python-build --dir /app/src
    [...]
    不允许ONBUILD使用链接指令ONBUILD ONBUILD。
    ONBUILD只会继承给子节点的镜像,不会再继承给孙子节点。
    ONBUILD不会触发FROM、MAINTAINER指令。

    ENV 在构建的镜像中设置环境变量,在后续的Dockerfile指令中可以直接使用,也可以固化在镜像里,在容器运行时仍然有效。 ENV指令有两种格式:
    ENV :把第一个空格之后的所有值都当做的值,无法在一行内设定多个环境变量。
    ENV = ...:可以设置多个环境变量,如果中存在空格,需要转义或用引号"括起来。
    ENV myName John Doe
    ENV myDog Rex The Dog
    ENV myCat fluffy
    或者

    ENV myName="John Doe" myDog=Rex The Dog
    myCat=fluffy
    推荐使用第二种,同样的这样能减少图层提高效率。

    注意:可以在容器运行时指定环境变量,替换镜像中的已有变量,docker run --env <key>=<value>。
    使用ENV可能会对后续的Dockerfile指令造成影响,如果只需要对一条指令设置环境变量,可以使用这种方式:RUN <key>=<value> <command>

    ENTRYPOINT 指定镜像的执行程序。ENTRYPOINT指令有两种格式:
    ENTRYPOINT ["executable", "param1", "param2"] (执行格式,首选)
    ENTRYPOINT command param1 param2 (shell格式)
    CMD和ENTRYPOINT至少得使用一个。ENTRYPOINT应该被当做docker的可执行程序,CMD应该被当做ENTRYPOINT的默认参数。
    docker run <image> <arg1> <arg2> ...会把之后的参数传递给ENTRYPOINT,覆盖CMD指定的参数。可以用docker run --entrypoint
    来重置默认的ENTRYPOINT。

    STOPSIGNAL 触发系统信号。
    STOPSIGNAL signal
    STOPSIGNAL指令设置将发送到容器以退出的系统调用信号。此信号可以是与内核的SysCall表中的位置匹配的有效无符号数字(例如9),也可以是格式为SIGNAME的信号名称(例如SIGKILL)。


    HEALTHCHECK 增加自定义的心跳检测功能,多次使用只有最后一次有效。格式:
    HEALTHCHECK [OPTIONS] CMD command (通过在容器内运行命令来检查容器运行状况)
    HEALTHCHECK NONE (禁用从基础映像继承的任何运行状况检查)
    可选的OPTION:

    --interval=DURATION(检测间隔,默认值:30s)
    --timeout=DURATION(命令超时时间,默认值:30s)
    --start-period=DURATION(初始化后开始检查时间,默认值:0s)
    --retries=N(连续N次失败后标记为不健康,默认值:3次)
    Start Period为需要时间引导的容器提供初始化时间。在此期间的探测失败将不计入最大重试次数。但是,如果运行状况检查在开始期间成功,则容器将被视为已启动,并且所有连续失败将计入最大重试次数。

    <command>可以是shell脚本,也可以是exec格式的json数组。
    docker以<command>的退出状态码来区分容器是否健康,这一点同shell一致:

    0:命令返回成功,容器健康
    1:命令返回失败,容器不健康
    2:保留状态码,不要使用
    举个栗子:每5分钟检测本地网页是否可访问,超时设为3秒:

    HEALTHCHECK --interval=5m --timeout=3s
    CMD curl -f http://localhost/ || exit 1
    复制代码你可以使用docker inspect命令查看健康状态。
    当容器的运行状况发生更改时,将生成带有新状态的health_status事件

    SHELL更改后续的Dockerfile指令中所使用的shell。默认的shell是["bin/sh", "-c"]。可多次使用,每次都只改变后续指令。

    SHELL ["executable", "parameters"]

    特别注意
    在上面的描述中可以看到有两组指令在功能上都差不多,但也是有区别的:

    RUN、CMD、ENTRYPOINT执行脚本的指令
    三个指令都是执行脚本
    RUN是在创建镜像是执行,即使用docker build命令时执行,在一个Dockerfile里面可以有多个RUN
    CMD和ENTRYPOINT是在运行容器时执行,即使用docker run命令时执行,这两个指令在Dockerfile中都只有最行一条被执行
    CMD在使用docker run时可以加参数将Dockerfile中的CMD覆盖
    ENTRYPOINT在Dockerfile中出现后就一定会在docker run时被执行,不必担心会被其他参数所覆盖。
    ADD、COPY拷贝文件(夹)到容器
    ADD拷贝文件(夹)时可以指定本地文件、远程URL地址,如果拷贝的是tar文件时将会被自动解压成文件夹
    COPY拷贝文件(夹)时不可以指定远程URL地址,拷贝tar文件也不会被自动解压成文件夹,在拷贝本地文件时建议使用COPY

    
    

    最佳实践

    容器应该是短暂的

    通过 Dockerfile 构建的镜像所启动的容器应该尽可能短暂 (ephemeral)。短暂意味着可以很快地启动并且终止

    使用 .dockerignore 排除构建无关文件

    .dockerignore 语法与 .gitignore 语法一致。使用它排除构建无关的文件及目录,如 node_modules

    使用多阶段构建

    多阶段构建可以有效减小镜像体积,特别是对于需编译语言而言,一个应用的构建过程往往如下

    1. 安装编译工具
    2. 安装第三方库依赖
    3. 编译构建应用

    而在前两步会有大量的镜像体积冗余,使用多阶段构建可以避免这一问题

    避免安装不必要的包

    减小体积,减少构建时间。如前端应用使用 npm install --production 只装生产环境所依赖的包。

    一个容器只做一件事

    如一个web应用将会包含三个部分,web 服务,数据库与缓存。把他们解耦到多个容器中,方便横向扩展。如果你需要网络通信,则可以将他们至于一个网络下。

    减少镜像层数

    只有 RUN, COPY, ADD 会创建层数, 其它指令不会增加镜像的体积
    尽可能使用多阶段构建
    使用以下方法安装依赖

    RUN yum install -y node python go

    将多行参数排序

    便于可读性以及不小心地重复装包

    RUN apt-get update && apt-get install -y 
      bzr 
      cvs 
      git 
      mercurial 
      subversion

    充分利用构建缓存

    在镜像的构建过程中 docker 会遍历 Dockerfile 文件中的所有指令,顺序执行。对于每一条指令,docker 都会在缓存中查找是否已存在可重用的镜像,否则会创建一个新的镜像

  • 相关阅读:
    【转】Android中设置TextView的颜色setTextColor
    【转】android颜色对应的xml配置值
    【转】color颜色十六进制编码大全
    【转】Usage of sendBroadcast()
    【转】Android4.3 蓝牙BLE初步
    【转】android中重复连接ble设备导致的连接后直接返回STATE_DISCONNECTED的解决办法---不错不错,重新连接需要花费很长的时间
    【转】推荐--《Android深入浅出》----不错
    【转】google chrome如何设置主页
    【转】Chrome保存mhtml网页文件的方法 – 无需任何插件,完美!
    【转】Android--广播BroadcastReceiver
  • 原文地址:https://www.cnblogs.com/52py/p/15152083.html
Copyright © 2011-2022 走看看