美文网首页
Docker 指令详解

Docker 指令详解

作者: JhonHarrison | 来源:发表于2018-12-14 19:57 被阅读0次

    1. COPY 复制文件

    格式:

    COPY [--chown=<user>:<group>] <源路径>... <目标路径>
    COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]

    COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。

    <源路径> 可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的filepath.Match 规则。

    源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。这个特性对于镜像定制很有用。特别是构建相关文件都在使用 Git 进行管理的时候。

    2. ADD 更高级的复制文件

    ADD 指令和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能。

    • 比如 <源路径> 可以是一个 URL。Docker 引擎会试图去下载这个链接的文件放到 <目标路径> 去。下载后的文件权限自动设置为 600。
    • 如果 <源路径> 为一个 tar 压缩文件的话,压缩格式为 gzip , bzip2 以及xz 的情况下, ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。
    但需要注意的是:

    ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。
    COPY 和 ADD 指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD 。

    3. CMD 容器启动命令

    shell 格式: CMD <命令>
    exec 格式: CMD ["可执行文件", "参数1", "参数2"...]
    参数列表格式: CMD ["参数1", "参数2"...] 。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。

    Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的。

    在指令格式上,一般推荐使用 exec 格式,这类格式在解析时会被解析为 JSON数组,因此一定要使用双引号,而不要使用单引号。
    如果使用 shell 格式的话,实际的命令会被包装为 sh -c 的参数的形式进行
    执行.比如:
    CMD echo $HOME
    CMD [ "sh", "-c", "echo $HOME" ]

    Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 upstart/systemd 去启动后台服务,容器内没有后台服务的概念.
    CMD service nginx start

    使用 service nginx start 命令,则是希望 upstart 来以后台守护进程形式启
    动 nginx 服务。而刚才说了 CMD service nginx start 会被理解为 CMD [
    "sh", "-c", "service nginx start"] ,因此主进程实际上是 sh 。那么当
    service nginx start 命令结束后, sh 也就结束了, sh 作为主进程退出
    了,自然就会令容器退出。

    正确的做法是直接执行 nginx 可执行文件,并且要求以前台形式运行。

    CMD ["nginx", "-g", "daemon off;"]
    

    4. ENTRYPOINT 入口点

    ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也可以替代,不过需要通过docker run 的参数 --entrypoint 来指定。
    当指定了 ENTRYPOINT 后, CMD 的含义就发生了改变,不再是直接的运行其命
    令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令.

    <ENTRYPOINT> "<CMD>"
    

    这个镜像在运行时,无法接受任何参数。

    FROM ubuntu:18.04
    RUN apt-get update \
    && apt-get install -y curl \
    && rm -rf /var/lib/apt/lists/*
    CMD [ "curl", "-s", "https://ip.cn" ]
    

    使用ENTRYPOINT就可以在运行镜像时,docker run myip -i 执行成功。这里 -i 是新的 CMD ,因此会作为参数传给curl。

    FROM ubuntu:18.04
    RUN apt-get update \
    && apt-get install -y curl \
    && rm -rf /var/lib/apt/lists/*
    ENTRYPOINT [ "curl", "-s", "https://ip.cn" ]
    

    5. ENV 设置环境

    ENV <key> <value>
    ENV <key1>=<value1> <key2>=<value2>.

    6. ARG 构建

    格式: ARG <参数名>[=<默认值>]

    构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是, ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在的。
    Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用 --build-arg <参数名>=<值> 来覆盖。
    注意:
    在 1.13 之前的版本,要求 --build-arg 中的参数名,必须在 Dockerfile 中用 ARG 定义过.

    7. VOLUME 定义匿名卷

    VOLUME ["<路径1>", "<路径2>"...]
    VOLUME <路径>
    为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。

    8. EXPOSE 声明端口

    EXPOSE <端口1> [<端口2>...]

    EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务.
    在 Dockerfile 中写入这样的声明有两个好处:
    一,是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;
    二,是在运行时使用随机端口映射时,也就是 docker run -P时,会自动随机映射 EXPOSE 的端口。

    9. WORKDIR 指定工作目录

    WORKDIR <工作目录路径>

    使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在, WORKDIR 会帮你建立目录。

    10. USER 指定当前用户

    USER <用户名>[:<用户组>]

    USER 指令和 WORKDIR 相似,都是改变环境状态并影响以后的层。 WORKDIR是改变工作目录, USER 则是改变之后层的执行 RUN , CMD 以及ENTRYPOINT 这类命令的身份.

    # 建立 redis 用户,并使用 gosu 换另一个用户执行命令
    RUN groupadd -r redis && useradd -r -g redis redis
    # 下载 gosu
    RUN wget -O /usr/local/bin/gosu "https://github.creleases/download/1.7/gosu-amd64" \
        && chmod +x /usr/local/bin/gosu \
        && gosu nobody true
    # 设置 CMD,并以另外的用户执行
    CMD [ "exec", "gosu", "redis", "redis-server" ]
    

    11. HEALTHCHECK 健康检查

    HEALTHCHECK [选项] CMD <命令> :设置检查容器健康状况的命令
    HEALTHCHECK NONE :如果基础镜像有健康检查指令,使用这行可以屏蔽掉
    其健康检查指令

    这是Docker 1.12 引入的新指令.
    当在一个镜像指定了 HEALTHCHECK 指令后,用其启动容器,初始状态会为starting ,在 HEALTHCHECK 指令检查成功后变为 healthy ,如果连续一定次数失败,则会变为 unhealthy .

    --interval=<间隔> :两次健康检查的间隔,默认为 30 秒;
    --timeout=<时长> :健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
    --retries=<次数> :当连续失败指定次数后,则将容器状态视为unhealthy ,默认 3 次

    和 CMD , ENTRYPOINT 一样, HEALTHCHECK 只可以出现一次,如果写了多个,
    只有最后一个生效。
    命令的返回值决定了该次健康检查的成功与否: 0 :成功; 1 :失败; 2 :保留

    FROM nginx
    RUN apt-get update && apt-get install -y curl && rm -rf /var/lib
    /apt/lists/*
    HEALTHCHECK --interval=5s --timeout=3s \
    CMD curl -fs http://localhost/ || exit 1
    

    为了帮助排障,健康检查命令的输出(包括 stdout 以及 stderr )都会被存储于健康状态里,可以用 docker inspect 来查看。

    $ docker inspect --format '{{json .State.Health}}' web | python -m json.tool
    

    12. ONBUILD 为他人做嫁衣裳

    ONBUILD <其它指令>

    ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUN , COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。

    相关文章

      网友评论

          本文标题:Docker 指令详解

          本文链接:https://www.haomeiwen.com/subject/gbjmhqtx.html