• Dcokerfile 参考


    Dcokerfile 包含了所有用来组装image的命令。通过docker build来自动创建image。
     
    用法

    需要指定本地路径作为上下文目录,路径是本地系统的目录。而docker build会递归的从指定目录去寻找。
    $ docker build .
    Sending build context to Docker daemon 6.51 MB ...
     
    一般情况下,指定空目录且Dockerfile也在该目录中。当然也可以使用-f 来指定Dockerfile的位置。
    $ docker build -f /path/to/a/Dockerfile .
    如果构建成功,您可以指定要保存的image的存储库和标记:
    zane@zane-V:~/mydockerbuild$ docker build -t aiapple .
    #生成了aiapple存储库的image。
    zane@zane-V:~/mydockerbuild$ docker images
    REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
    aiapple                 latest              d2f5f84bec87        26 seconds ago      275.1 MB
    在创建image后,指定新image标记到多个存储库;
    zane@zane-V:~/mydockerbuild$ docker build -t zane/aiapple:007 -t zane/aiapple:009 .
    Sending build context to Docker daemon 2.048 kB
    Step 1 : FROM docker/whalesay:latest
     ---> 6b362a9f73eb
    Step 2 : RUN apt-get -y update && apt-get install -y fortunes
     ---> Using cache
     ---> 845104a653c5
    Step 3 : CMD /usr/games/fortune -a | cowsay
     ---> Using cache
     ---> d2f5f84bec87
    Successfully built d2f5f84bec87
    zane@zane-V:~/mydockerbuild$ docker images
    REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
    ziapple                 latest              d2f5f84bec87        7 minutes ago       275.1 MB
    aiapple                 latest              d2f5f84bec87        7 minutes ago       275.1 MB
    zane/aiapple            007                 d2f5f84bec87        7 minutes ago       275.1 MB
    zane/aiapple            009                 d2f5f84bec87        7 minutes ago       275.1 MB
    注意:
    • 存仓库不支持大写
    • 所有存储库使用的image还是一个。
      • 当然run的时候是指定 存储库。
      • 删除image的时候实际上是删除存储库
        • docker rmi ziapple
     
    为了创建image的效率,docker build 使用中间image(cache)。
     
    格式

     
    Dockerfile第一行必须是:
    ‘FROM’用来指定基础image。
     
    语法解析器
    两种无效的写法:
     
    解析器要连续书写
    # direc
    ive=value
     
    解析器出现了两次
    # directive=value1
    # directive=value2
     
    FROM ImageName
     
    解析器被认为是注释,因为在创建image说的之后。
    FROM ImageName
    # directive=value
     
    无效解析器被认为是注释,而注释之后的解析器 认为无效
    # unknowndirective=value
    # knowndirective=value
     
    所有解析器指令必须位于Dockerfile的最顶端。类似脚本中#!/bin/bash ;
    惯例解析器,小写,以及后面紧跟空行。
     
    环境替换
    环境变量值,可以使用在Dockerfile中。
    在Dockerfile中使用$variable_name,
     
    bash的几个特性:
    • ${variable:-word}
      • 如果variable设置,则返回variable的值,否则返回word
    • ${variable:+word}
      • 如果variable设置,则返回word,否则返回空字符串
     
    FROM busybox
    ENV foo /bar
    WORKDIR ${foo} # WORKDIR /bar
    ADD . $foo # ADD . /bar
    COPY $foo /quux # COPY $foo /quux
    • ADD
    • COPY
    • ENV
    • EXPOSE
    • LABEL
    • USER
    • WORKDIR
    • VOLUME
    • STOPSIGNAL
     
    ENV abc=hello
    ENV abc=bye def=$abc
    ENV ghi=$abc
    def的值是hello 不是bye。而ghi的值是bye。
    可见是一行行整体执行的。
     
    .dockerignore file

     
    在docker发送上下文给 docker daemon 之前,会寻找.dockerignore file文件,去排除一些不需要的文件,或者很大的文件
    不把这些文件发送给docker daemon,提升效率。而如果之后需要用到,则可以使用 ADD 或者 COPY 把他们放进image中。
     
    .dockerignore 文件第一行是:
    # comment
     
    .dockerignore 支持正则表达式,
    # comment
         */temp*
         */*/temp*
         temp?
    • #comment
      • 忽略,只是语法需要
    • */temp*
      • 排除任何root目录中间子目录名以temp开始的文件或目录
      • /ttt/templlll
    • */*/temp*
      • /somedir/subdir/temporary
    • temp?
      • /tempa 或 /tempb
     
    具体排除规则: filepath.Match rules
     
    使用! ,排除例外。
    *.md
    !README*.md
    README-secret.md
    所有.md 结尾的文件,但是不包含REME开头的.md文件,但README-secret.md 除外。README-secret.md 是包含的。
     
    考虑一下:
    *.md
    README-secret.md
    !README*.md
    所有的.md结尾的文件,和README-secret.md文件。不包含以README开头的.md文件。即README-secret.md是不包含的。
     
    类似于Linux中IPtables 规则的配置,是按照顺序来的。
     
    FROM

     
    FROM <image>
    or
    FROM <image>:<tag>
    or
    FROM <image>@<digest>
    设置基础image。
     
    • FROM在Dockerfile中必须是除注释外的第一行
    • FROM在一个Dockerfile中出现多次为了创建多个images.
    • tag 或者 digest 值是选项。如果忽略这两个,则使用默认值latest。
      • 如果没有能匹配到tag的值,会放回错误
     
    MAINTAINER

     
    MAINTAINER <name>
    maintainer,指定制作这个image的作者。
     
    RUN

     
    两种形式
    • RUN <command>
      • shell 形式,这个命令运行在一个shell中,默认shell是 /bin/sh -c 
    • RUN ["executable","param1","param2"]
      • 执行 形式
     
    run 执行任何命令然后提交执行结果。已经提交执行结果的image在后面的步骤会被使用到。
     
    使用反斜杠 用来将一个命令分两行写
    RUN /bin/bash -c 'source $HOME/.bashrc;
    echo $HOME'
    注意:
    • 使用执行形式,指定不同shell
      • RUN ["/bin/sh","-c","echo hello"]
    • 执行形式,需要双引号
    • 和shell形式不同,执行形式不调用命令行shell。
      • 也就是说一般shell进程不会启动
        • RUN ["echo","$HOME"],$HOME变量不会被替换,
        • 即没有环境变量之说,因为shell 进程都没起来
      • 但如果想用shell进程但又不想使用shell形式,则
        • RUN ["sh","-c","echo $HOME"]
        • 在执行形式,指定shell。
    用户RUN指令的缓存在下一次构建期间不会自动失效。像RUN apt-get dist-upgrade -y 在缓存中则在下一次build也会被使用。
     
    --no-cache,使缓存失效。
    docker build --no-cache
    ADD指令也会使缓存失效
     
    CMD

     
    cmd有三种形式:
    • CMD ["executable","param1","param2"] 
      • 首选形式
    • CMD ["param1","param2"]
      • 最为entrypoint,默认参数
    • CMD command param1 param2 
      • shell 形式
    Dockerfile中只有最后一个CMD是起作用的。
     
    CMD的最主要的目的就是为执行中的container提供默认参数。默认参数可以包含可执行的文件。
    注意:
    • 不像shell 形式,首选形式不调用shell 命令行,shell进程不会启动。因此
    • CMD [ "echo", "$HOME" ] 则在HOME没有变量的替换。
    • CMD [ "sh", "-c", "echo $HOME" ] 才会使用变量的替换
     
    CMD作用就是在运行image时,设置一些同步运行的命令。
     
    如果使用shell 形式,command将会在/bin/sh -c 下执行的
    FROM ubuntu
    CMD echo "This is a test." | wc -
     
    首选形式
    FROM ubuntu
    CMD ["/usr/bin/wc","--help"]
    如果在docker run 中指定参数,则会覆盖原来在CMD中默认指定的参数。
    • run,实际上是执行命令然后提交执行结果
    • cmd,在build时不执行任何命令,但为image指定了将要执行的命令
     
    LABEL

     
    LABEL <key>=<value> <key>=<value> <key>=<value> ...
     
    LABEL 增加元数据到image。一个LABEL是键值对。
    例子:
    LABEL "com.example.vendor"="ACME Incorporated"
    LABEL com.example.label-with-value="foo"
    LABEL version="1.0"
    LABEL description="This text illustrates 
    that label-values can span multiple lines."

    每个LABEL都会产生一个layer,如果有很多layer的话可能会导致image不工作。

     
    单个image layer
    LABEL multi.label1="value1" multi.label2="value2" other="value3"
     
    也可以是
    LABEL multi.label1="value1" 
          multi.label2="value2" 
          other="value3"
    如果原来已经存在的key,后面的 LABEL会使用新的覆盖。
     
    查看image labels: docker inspect
     
    EXPOSE

     
    EXPOSE <port> [<port>...]
     
    指定容器在运行的时候监听的端口
     
    ENV

     
    ENV <key> <value>
    ENV <key1>=<value> <key2>=<value>...
     
    设置环境变量<key> 值为<value>
     
    更改环境变量
    docker run --env <key>=<value>
     
     
    ADD

     
    add有两种形式
    • ADD <src>... <dest>
    • ADD ["<src>",..."<dest>"]
      • 这种形式适合路径包含空白。
     
    ADD命令从<src>复制文件 到 image文件系统的<dest>
     
    每个<src>可以包含通配符,使用 filepath.Match原则进行匹配
    ADD hom* /mydir/           # adds all files starting with "hom"
    ADD hom?.txt /mydir/       # ? is replaced with any single character, e.g., "home.txt"
    <dest>是绝对路径或者是WORKDIR的相对路径。
    ADD test relativeDir/ # adds "test" to `WORKDIR`/relativeDir/
    ADD test /absoluteDir/ # adds "test" to /absoluteDir/
    所有的新文件和目录是被UID,GID 为0所创建的。即使root了。
     
    如果<src>是远程URL文件,那么目标文件需要600权限
     
    ADD 服从一下规则:
    • <src>路径必须在build的上下文中。
      • 不能使用ADD ../something  /something。.. 已经不再上下文中了
      • 因为docker build的第一步就是讲上下文目录发送到docker  daemon
    • <src>是一个URL,<dest>没有以斜线结束,文件从URL下载然后复制到<dest>
    • <src>是一个URL,<dest>以斜线结束,然后filename依据URL推断,file被下载到<dest>/<filename>.
    • <src>是一个目录,则整个目录中的内容都会被复制.
      • 注意目录本身不会复制,仅复制目录中的内容
    • 如果<dest>没有以斜杠结束,它会被认为一个常规文件,<src>内容会被写在<dest>中
     
    COPY

     
    有两种形式:
    • COPY <src>... <dest>
    • COPY ["<src>",... "<dest>"]
      • 这种形式要求路径包含空白
     
    COPY 从<src>复制新的文件或目录到容器的文件系统当中的<dest>
     
    使用通配符进行匹配:
    COPY hom* /mydir/      # adds all files starting with "hom"
    COPY hom?.txt /mydir/  # ? is replaced with any single character, e.g., "home.txt"
    <dest>是绝对路径,或者相对WORKDIR的路径
    COPY test relativeDir/  # adds "test" to `WORKDIR`/relativeDir/
    COPY test /absoluteDir/ # adds "test" to /absoluteDir/
    所有的新文件和目录是被UID,GID 为0所创建的。即使root了。
     
    COPY规则类似ADD
     
    ENTRYPOINT

     
    有两种形式:
    • ENTRYPOINT ["executable", "param1", "param2"]  
      • 首选形式
    • ENTRYPOINT command param1 param2
      • shell 形式
     
    ENTRYPOINT 允许你配置容器。
    例子:
    启动nginx使用其默认配置,监听端口80
    docker run -i -t --rm -p 80:80 nginx
    • docker run <image>命令行的所有参数,
      • 会添加在exec形式的ENTRYPOINT中的元素之后,并将覆盖使用CMD指定的所有元素。
    • docker run <image> -d argument,允许将参数传送到ENTRYPOINT
    • 覆盖ENTRYPOINT 使用  docker run --entrypoint
    在Dockerfile中只有最新的ENTRYPOINT会生效。
     
    exec 形式例子
    使用entrypoint exec 形式设定那些默认不改变参数和命令,
    使用CMD设定那些可能会改变的参数。
     
    FROM ubuntu
    ENTRYPOINT ["top", "-b"]
    CMD ["-c"]
    shell 形式例子
    FROM ubuntu
    ENTRYPOINT exec top -b
     
    cmd 和 entrypoint 
    • Dockerfile需要至少指定一个CMD或者ENTRYPOINT命令
    • 当使用容器作为可执行文件时,应该定义ENTRYPOINT
    • CMD来用作为定义ENTRYPOIN默认参数的一种途径或者
      • 容器中执行ad-hoc命令
    • 当运行容器并带有可变参数时CMD会被覆盖
     
    VOLUME

     
    VOLUME ["/data"]
    volume 创建一个指定名字的挂载点,并将它作为本地或者其他容器的外部挂载的数据卷
     
    docker run 用在基础image中被指定的本地已经存在的数据初始化新建的数据卷。
    例子:
    FROM ubuntu
    RUN mkdir /myvol
    RUN echo "hello world" > /myvol/greeting
    VOLUME /myvol
     
    上面的 基础image中,/myvol 已经有数据文件greeting 此时又指定了 VOLUME 创建新的数据卷,
    则将 greeting文件复制到新数据卷。
     
    USER

     
    USER daemon
     
    WORKDIR

     
    WORKDIR /path/to/workdir
     
    可以多次被使用:
    例子:
    WORKDIR /a
    WORKDIR b
    WORKDIR c
    RUN pwd
    pwd命令最终的输出结果,会是 /a/b/c
     
    可以联合环境变量使用
    例子:
    ENV DIRPATH /path
    WORKDIR $DIRPATH/$DIRNAME
    RUN pwd
    pwd命令最终的输出结果,是/path/$DIRNAME
     
    ARG

     
    ARG <name>[=<default value>]
    ARG定义一个参数,使用用户在使用docker build 时可以传送到docker build 通过 --build-arg <varname>=<value>。
     
    可以指定一个或多个
    FROM busybox
    ARG user1
    ARG buildno ...
    ARG有默认值,且在build时没值传给 docker build 则使用ARG 默认值。
     
    ARG值在Dockerfile定义的时就已经生效,而不是在执行的时候。
    例子:
    1 FROM busybox
    2 USER ${user:-some_user}
    3 ARG user
    4 USER $user...
     
    通过这个Dcokerfile build
    $ docker build --build-arg user=what_user Dockerfile
     
    第二行USER 评估 some_user 作为 第三行 user参数的定义值。
    第四行USER 认为从命令行传过来的 what_user  作为user参数的定义值。
    在通过ARG指令定义之前,变量的任何使用都将导致空字符串。
     
    ENVIRONMENT 参数定义会覆盖 同名的ARG定义:
    1 FROM ubuntu
    2 ARG CONT_IMG_VER
    3 ENV CONT_IMG_VER v1.0.0
    4 RUN echo $CONT_IMG_VER
    通过这个Dockerfile build
     
    $ docker build --build-arg CONT_IMG_VER=v2.0.1 Dockerfile
    这个例子中,会使用v1.0.0 替代命令行传入的 v2.0.1.
    这像是shell 脚本中 本地环境变量 会 替代 通过参数传入过来的环境变量。
     
    build缓存的影响
     
    ARG 变量不会作为环境变量持久化到image中。
    然而它会在一些地方对build缓存存在一些影响。
    如果Dockerfile定义了不同于之前build的 ARG 变量值时,缓存丢失会在第一次使用的时候出现,但值不是它原来的定义。
    一般情况,在ARG 后立即接RUN,可以解决缓存丢失问题。
     
    例子:两个Dockerfile
    1 FROM ubuntu
    2 ARG CONT_IMG_VER
    3 RUN echo $CONT_IMG_VER
     
    1 FROM ubuntu
    2 ARG CONT_IMG_VER
    3 RUN echo hello
    在两个文件命令中,都在命令行指定CONT_IMG_VER 值,--build-arg CONT_IMG_VER =<value> 。
    在指定的第2行都不会 产生 缓存丢失;在第3行会产生缓存丢失;
    ARG CONT_IMG_VER会使RUN 这行被标识为与运行CONT_IMG_VER = <value> 和 echo hello相同,
    如果<value> 改变,缓存便会丢失。
     
    另一个例子:
    1 FROM ubuntu
    2 ARG CONT_IMG_VER
    3 ENV CONT_IMG_VER $CONT_IMG_VER
    4 RUN echo $CONT_IMG_VER
     
    缓存丢失出现在了第三行,丢失原因是ENV参照ARG参数,然而这个参数在命令行被修改了。
     
     
    ONBUILD

    onbuild 在image中增加一个触发器,当这个image被作为其他image的基础image时,执行。
     
     
    [...]
    ONBUILD ADD . /app/src
    ONBUILD RUN /usr/local/bin/python-build --dir /app/src
    [...]
     
    STOPSIGNAL

     
    STOPSIGNAL signal
    设置容器退出的 信号名称
     
     
    HEALTHCHECK

    两个形式:
    • HEALTHCHECK [OPTIONS] CMD command  
      • 通过运行一个容器内部的命令来检测容器是否健康
    • HEALTHCHECK NONE
      • 关闭任何来自基础image的 健康检测
     
    告诉docker如何去检测容器是否仍然在工作。
    options
    • --interval=DURATION (default: 30s)
    • --timeout=DURATION (default: 30s)
    • --retries=N (default: 3)
     
    状态值
    • 0: success 
    • 1: unhealthy
    • 2: reserved 
    例子:
    HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
     
    总结

     
    • 指定dockerfile位置,以及使用-t 指定image 名称
    • .dockerignore file
      • 排除一些不需要的文件,支持正则表达式
      • 文件第一行
        • # comment
          • 仅是语法需要
      • 使用! 来双否定,即表示需要的文件
        • *.md
        • !README*.md
        • 排除以.md结尾的文件,但是要包含以README开头 .md 结尾的文件。
    • 主要语法
      • FROM
        • 设置基础image
      • MAINTAINER
        • 指定作者
      • RUN
        • 两种形式
          • RUN <command>
            • shell 形式,这个命令运行在一个shell中,默认shell是 /bin/sh -c 
            • RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
          • RUN ["executable","param1","param2"]
            • 执行 形式
            • RUN ["echo","$HOME"]
        • 执行结果在后面会被使用到
        • 用户RUN指令的缓存在下一次构建期间不会自动失效。
          • --no-cache,使缓存失效。
      • CMD
        • Dockerfile中只有最后一个CMD是起作用的。
        • CMD的最主要的目的就是为执行中的container提供默认参数。
          • cmd,在build时不执行任何命令,但为image指定了将要执行的命令
        • 主要形式
          • CMD ["executable","param1","param2"] 
      • ENTRYPOINT
        • ENTRYPOINT 允许你配置容器。如Nginx 端口号之类
        • 在Dockerfile中只有最新的ENTRYPOINT会生效
        • CMD & ENTRYPOINT
          • 使用entrypoint exec 形式设定那些默认不改变参数和命令,
          • 使用CMD设定那些可能会改变的参数。
          • Dockerfile需要至少指定一个CMD或者ENTRYPOINT命令
      • LABEL
        • LABEL 增加元数据到image。一个LABEL是一个键值对。
        • 每个LABEL都会产生一个layer,如果有很多layer的话可能会导致image不工作
        • 单个image layer
          • LABEL multi.label1="value1" multi.label2="value2" other="value3"
        • 查看image labels
          • docker inspect
      • EXPOSE
        • 指定容器在运行的时候监听的端口
      • ENV
        • 设置环境变量<key> 值为<value>
        • ENV <key1>=<value> <key2>=<value>...
      • ADD
        • ADD命令从<src>复制文件 到 image文件系统的<dest>
      • COPY
        • COPY 从<src>复制新的文件或目录到容器的文件系统当中的<dest>
      • VOLUME
        • volume 创建一个指定名字的挂载点
      • ARG
        • ARG定义一个参数,使用户在使用docker build 时通过 --build-arg <varname>=<value> 传入
        • ARG <name>[=<default value>]
        • 注意:需要给定默认值
  • 相关阅读:
    Python笔记:高阶函数
    linux C生成UUID的方法
    c语言连接mysql完整演示
    linux下C语言连接mysql数据库演示(在控制台编译的)
    mysql版本问题,导致的mysql.user表下面的字段变成了authentication_string
    选择排序算法
    汉诺塔递归实现
    操作系统复习第一章
    二叉树的基本操作
    字符串的模式匹配算法
  • 原文地址:https://www.cnblogs.com/Aiapple/p/6971690.html
Copyright © 2020-2023  润新知