美文网首页云原生
06-Dockerfile命令

06-Dockerfile命令

作者: 紫荆秋雪_文 | 来源:发表于2021-10-22 20:37 被阅读0次

    Dockerfile命令

    一、Dockerfile

    Dockerfile由一行行命令语句组成。一般而言,Dockerfile可以分为四部分:基础镜像信息、维护信息、镜像操作指令、启动时执行指令

    image.png
    • FROM指定基础镜像,最好挑一些 apline,slim 之类的基础小镜像
    • scratch镜像是一个空镜像,常用于多阶段构建

    二、RUN

    • RUN指令在当前镜像层顶部的新层执行任何命令,并提交结果,生成新的镜像层
    • 生成的提交镜像将用于Dockerfile的下一步。分层运行RUN指令并生成提交符号Docker的核心概念,就想源代码控制一样
    • exec形式命令可以避免破坏 shell字符串,并使用不包含指定shell可执行文件的基本镜像运行RUN命令。可以使用shell命令更改shell形式的默认shell。在shell形式中,您可以使用(反斜杠)将一条RUN指令继续到下一行
    RUN <command>(shell形式,/bin/sh -c 的方式运行,避免破坏 shell 字符串)
    RUN ["executable", "param1", "param2"](exec 形式)
    

    1、实例测试

    • Dockerfile 文件
    FROM alpine
    LABEL   maintainer=Raven xinshi=Wang  # 附近信息
    ENV msg = "Hello World"  #定义 环境变量
    RUN echo $msg
    RUN ["echo", "$msg"]
    RUN /bin/sh -c 'echo $msg'
    RUN ["/bin/sh", "-c", "echo $msg"]
    
    • 使用Dockerfile文件构建本地镜像
    # docker build -t 镜像名称
    docker build -t test/myapp .
    # 不使用缓存
    docker build --no-cache -t raven/test3 .
    
    • 输出
    Sending build context to Docker daemon  77.82kB
    Step 1/7 : FROM alpine
     ---> 14119a10abf4
    Step 2/7 : LABEL   maintainer=Raven xinshi=Wang
     ---> Running in b2d7f6e38073
    Removing intermediate container b2d7f6e38073
     ---> fae0897bf471
    Step 3/7 : ENV msg = "Hello World"
     ---> Running in cd3ca7432b87
    Removing intermediate container cd3ca7432b87
     ---> b33af3d9eac3
    Step 4/7 : RUN echo $msg  ##使用  echo 模式可以取出环境变量中的值
     ---> Running in e18551f17104
    = Hello World
    Removing intermediate container e18551f17104
     ---> bc3abc7fe94c
    Step 5/7 : RUN ["echo", "$msg"]  ##使用  exec 模式无法取出环境变量中的值
     ---> Running in 819fe9ffc7e5
    $msg
    Removing intermediate container 819fe9ffc7e5
     ---> 29d5a4c3032a
    Step 6/7 : RUN /bin/sh -c 'echo $msg'  ##使用  sh 模式直接取出环境变量中的值
     ---> Running in fff5e64394c1
    = Hello World
    Removing intermediate container fff5e64394c1
     ---> 90405522a350
    Step 7/7 : RUN ["/bin/sh", "-c", "echo $msg"]  ##使用  exec 模式直接取出环境
     ---> Running in 62e0db2c9f52
    = Hello World
    Removing intermediate container 62e0db2c9f52
     ---> bc78919ab073
    Successfully built bc78919ab073
    Successfully tagged raven/test3:latest
    

    小结

    • 由于 [ ] 不是shell形式,所以不能输出变量信息,而是输出$msg。其他任何 /bin/sh -c 的形式都可以输出变量信息
    • shell 是 /bin/sh -c <command> 的格式
    • exec 是 ["/bin/sh", "-c", command] 的格式 等价于 shell 方式
    • exec 默认方式不会进行变量替换

    三、CMD 和 ENTRYPOINT

    1、CMD 的三种写法

    • CMD ["executable", "param1", "param2"],exec方式,推荐
    • CMD ["param1", "param2"] 为 ENTRYPOINT 提供默认参数
    • CMD command param1 param2 shell 格式

    2、ENTRYPOINT 的两种写法

    • ENTRYPOINT ["executable", "param1", "param2"] exec方式,推荐
    • ENTRYPOINT command param1 param2 shell格式

    3、只能有一个CMD

    • Dockerfile中只能有一条 CMD 指令。如果列出多个 CMD,则只有最后一个CMD才会生效
    • CMD 的主要目的是为执行中的容器提供默认值。这些默认值可以包含可执行文件,也可以省略可执行文件,在这种情况下,还必须指定 ENTRYPOINT 指令

    4、CMD 为 ENTRYPOINT 提供默认参数

    • 如果使用 CMD 为 ENTRYPOINT 指令提供默认参数,则 CMD 和 ENTRYPOINT 指令均应使用 JSON 数组格式指定

    5、指令小结 image.png

    四、ARG

    ARG 指令定义一个变量,可以在构建时 docker build 通过使用 --build-arg <varname>=<value>标志的命令将其传递给构建器。如果用户指定了未在Dockerfile中定义的构建参数,则构建会输出警告

    ARG <name>[=<default value>]
    

    1、Dockerfile 有效的ARG

    FROM
    Learn more about the "FROM" Dockerfile command.
     busybox
    ARG user1
    ARG buildno
    # ...
    

    警告:不建议在构建时来传递密钥,如GitHub密钥、用户凭证等docker history

    2、默认值

    一条 ARG指令可以选择包含一个默认值

    FROM busybox
    ARG user1=someuser
    ARG buildno=1
    # ...
    

    3、实战

    FROM alpine
    
    ARG msg="hello world"
    
    RUN echo $msg
    
    CMD echo $msg
    CMD ["/bin/sh", "-c", "echo 12345; echo $msg"]
    

    3.1、通过Dockerfile构建镜像,Dockerfile文件名称为Dockerfile_ARG

    docker build -t raven:test --no-cache -f Dockerfile_ARG .
    
    • -t 指定镜像名称及版本(raven:test)
    • --no-cache:不使用缓存来执行构建镜像
    • -f:指定Dockerfile文件路径
    • 1、指定路径
    docker build -t raven:test --no-cache -f /root/Dockerfiles/Dockerfile_ARG .
    
    • 2、如果Dockerfile文件是以 Dockerfile 为名
    docker build --no-cache -t raven:test .
    
    Dockerfile文件名为 Dockerfile 时.png
    • 3、构建输出
    Sending build context to Docker daemon  2.048kB
    Step 1/5 : FROM alpine
     ---> 14119a10abf4
    Step 2/5 : ARG msg="hello world"  #使用ARG定义变量并赋有默认值
     ---> Running in 43d888792aa5
    Removing intermediate container 43d888792aa5
     ---> bb7718e13663
    Step 3/5 : RUN echo $msg  
     ---> Running in f35a8d4d13ca
    hello world
    Removing intermediate container f35a8d4d13ca
     ---> 7e3c81cb6d6c
    Step 4/5 : CMD echo $msg
     ---> Running in ccc3e0ca8813
    Removing intermediate container ccc3e0ca8813
     ---> a5395b20fb48
    Step 5/5 : CMD ["/bin/sh", "-c", "echo 12345; echo $msg"]
     ---> Running in e74bbc97d2be
    Removing intermediate container e74bbc97d2be
     ---> 1b456c19fbbb
    Successfully built 1b456c19fbbb
    Successfully tagged raven:v1
    
    • 3.1、使用ARG订单变量,可以使用 RUN echo $msg 来输出msg变量值
    • 3.2、CMD echo $msg 这种方式无法取出ARG订单的变量
    • 4、通过Dockerfile文件构建镜像成功 构建镜像成功.png
    • 5、运行镜像
    docker run -it raven:v1
    
    运行镜像.png
    • RUN命令:是在构建镜像时输出信息

    • CMD命令:是在运行镜像时输出信息

    • CMD命令无法输出ARG变量的值

    • 6、在构建镜像是修改变量

    docker build --no-cache --build-arg msg="Raven" -t raven:v1 -f Dockerfile_ARG .
    
    image.png
    • ARG指令定义了一个变量,用户可以在构建时使用--build-arg=value,docker build 命令会将其传递给构建器
    • --build-arg 指定参数会覆盖 Dockerfile 中指定的同名参数
    • 如果用户指定了 未在Dockerfile中定义的构建参数,则构建会输出警告
    • ARG只在构建器有效,运行期无效
    • ARG变量定义从Dockerfile中定义的行开始生效
    • 使用ENV指令定义的环境变量始终会覆盖同名的ARG指令
    • 再次强调不建议使用构建时变量来传递:GitHub密钥、用户凭证等机密。因为构建时变量使用docker history是可见的

    五、ENV

    1、在构建阶段中所有后续指令的环境中使用,并且在许多情况下也可以内联替换
    2、引号和反斜杠可用于在值中包含空格
    3、ENV 可以使用 key value的写法,但是这种不推荐使用了,后续版本可能会删除
    4、docker run --env 可以修改这些值
    5、容器运行时 ENV 值可以生效
    6、ENV在 image 阶段就会被解析并持久化(docker inspect image)

    1、ARG定义的变量,ENV是否可以使用

    • Dockerfile
    FROM alpine
    ARG msg1="hello world"
    ENV msg2 = $msg1
    RUN echo $msg1
    RUN echo $msg2
    CMD ["/bin/bash", "-c", "echo msg1_$msg1; echo msg2_$msg2;"]
    
    • 生成镜像
    docker build --no-cache -t raven:re -f Dockerfile_ARG_ENV .
    
    编译输出.png
    • 创建容器
    docker run -it raven:re
    
    运行镜像.png
    • 总结
      • ARG 定义的参数无法在运行时输出默认值,但是可以在运行时通过参数(-e)来修改 ARG 类型的参数值
      • ENV 定义的参数在构建和运行阶段都可以使用

    2、ARG定义的变量,ENV是否可以使用但是在构建镜像时修改参数

    • Dockerfile文件和上面的一样
    • 构建镜像
    docker build --no-cache --build-arg msg1="Raven" -t raven:re -f Dockerfile_ARG_ENV .
    
    构建镜像输出.png
    • 运行镜像
    docker run -it raven:re
    
    运行镜像输出.png

    3、ENV参数 赋值给另外一个 ENV参数

    • Dockerfile
    FROM alpine
    ENV msg1="hello world"
    ENV msg2 = $msg1
    RUN echo $msg1
    RUN echo $msg2
    CMD ["/bin/sh", "-c", "echo msg1_$msg1; echo msg2_$msg2;"]
    
    • 构建镜像
    docker build --no-cache -t raven:env -f Dockerfile_ENV .
    
    构建输出信息.png
    • 运行镜像
    docker run -it raven:env
    
    运行输出信息.png

    4、构建时修改msg1值

    • Dockerfile文件与 上面 3 一样
    • 构建镜像
    docker build --no-cache --build-arg msg1="Raven" -t raven:env -f Dockerfile_ENV .
    
    构建镜像输出.png
    • 总结
      • 构建时无法修改 ENV 类型参数
      • 从这里可以得出 ARG 类型参数应用在构建阶段
    • 运行镜像
    docker run -e msg1="Raven" -it raven:env
    
    运行时输出.png

    六、总结

    1、在构建镜像阶段,无法修改 ENV 类型参数

    2、在运行镜像阶段,当 ENV 参数 msg2 = ENV参数类型msg1,修改msg1时,并不会修改 msg2

    image.png

    3、在构建阶段 ENV 类型参数的值已经确定,但是也可以在运行时通过(-e)命令来修改

    4、应用选择

    4.1:ARG参数:在运行期间无法使用默认值,但是可以通过 运行命令传参来使用,所以,不推荐在运行期间使用ARG类型参数

    4.2:ENV参数:在运行期间可以使用默认值,也可以使用命令参数来传值。但是在构建期间无法通过构建命令(--build-arg)来改变值,而是直接使用的默认值。

    七、ADD & COPY

    ADD

    ADD拥有自动下载远程文件和解压的功能

    • src 路径必须在构建的上下文中;不能使用../something /something这种方式,因为docker构建的第一步是将上下文目录(和子目录)发送到docker守护程序
    • 如果src是URL,并且dest不以斜杠结尾,则从URL下载文件并将其复制到dest
    • 如果dest以斜杠结尾,将自动推断出 URL 的名字(保留最后一部分),保存到dest
    • 如果src是目录,则将复制目录的整个内容,包括文件系统元数据

    7.1、远程文件(Redis)

    1、目标文件不带斜杠

    FROM alpine
    #1、如果是远程文件,自动下载
    ADD http://download.redis.io/releases/redis-6.0.6.tar.gz /dest
    
    RUN ls -l
    
    image.png
    • 进入容器 image.png

    2、目标文件带斜杠

    • Dockerfile
    FROM alpine
    #1、如果是远程文件,自动下载
    ADD http://download.redis.io/releases/redis-6.0.6.tar.gz /dest/
    
    RUN ls -l
    RUN cd /dest && ls -l
    
    image.png

    7.2、本地文件(宿主机)

    • Dockerfile
    FROM alpine
    #1、如果是远程文件,自动下载
    ADD http://download.redis.io/releases/redis-6.0.6.tar.gz /dest/
    
    #2、如果是本地压缩包,自动解压
    ADD *.tar.gz    /app/
    
    RUN ls -l
    RUN cd /dest && ls -l
    RUN cd /app && ls -l
    
    image.png
    image.png
    image.png

    COPY

    COPY [--chown=<user>:<group>] <src>... <dest>
    COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
    
    • --chown 功能仅在用于构建 Linux 容器的 Dockerfiles 上受支持,而在 Windows 容器上不起作用
    • COPY 指令从 src 复制新文件或目录,并将它们添加到容器的文件系统中,
    • 可以指定多个 src资源,但是文件和目录的路径将被解释为相对于构建上下文的源
    • 每个 src都可以包含通配符,并且匹配将使用 Go 的 filepath.Match规则进行

    COPY命令

    • 拷贝当前上下文,以home开始的所有资源
    COPY hom* /mydir/
    
    • ? 匹配单个字符
    COPY hom?.txt /mydir/
    
    • 目标路径如果设置为相对路径,则相对与 WORKDIR 开始,把 "test.txt" 添加到<WORKDIR>/relativeDir/
    COPY test.txt relativeDir/
    
    • 也可以使用绝对路径,复制到容器指定位置
    COPY test.txt /absoluteDir/
    
    • 所有复制的文件资源默认都是使用 uid(0)/gid(0)的用户,可以使用 --chown改变
    COPY --chown=55:mygroup files* /somedir/
    COPY --chown=bin files* /somedir/
    COPY --chown=1 files* /somedir/
    COPY --chown=10:11 files* /somedir/
    
    • 宿主文件的权限


      image.png
    • 使用COPY
    • Dockerfile
    FROM alpine
    
    COPY *.tar.gz    /app/
    RUN ls -l
    RUN cd /app && ls -l
    
    image.png
    • 设置权限
    • Dockerfile
    FROM alpine
    #设置文件权限
    COPY --chown=1000:1000 *.tar.gz    /app/
    RUN ls -l
    RUN cd /app && ls -l
    
    image.png

    八、WORKDIR 和 VOLUME

    8.1、WORKDIR

    • WORKDIR 指令为Dockerfile中跟随它的后续所有 RUNCMDENTRYPOINTCOPYADD指令设置工作目录。如果WORKDIR不存在,即使以后的Dockerfile指令中未使用它也将被创建。
    • WORKDIR指令可在Dockerfile中多次使用。如果提供了相对路径,则它将相对于上一个WORKDIR指令的路径
    WORKDIR  /a
    WORKDIR  b
    WORKDIR  c
    RUN pwd
    #结果  /a/b/c
    
    ENV DIRPATH=/path
    WORKDIR $DIRPATH/$DIRNAME
    RUN pwd
    #结果  /path/$DIRNAME
    
    • 实战:如果需要修该Nginx显示或者配置时
    • 1、首先需要进入容器
    docker exec -it 7ab174e8c7b2 /bin/bash
    
    • 2、寻找HTML资源
    cd usr/share/nginx/html/
    
    • 这样操作比较麻烦,可以使用WORKDIR来直接指定到常用的目录(usr/share/nginx/html/),这样进入容器后就会自动来到该目录
    • Dockerfile
    FROM nginx
    #   进入容器的指定目录
    WORKDIR /usr/share/nginx/html/
    
    image.png

    8.2、VOLUME

    • 把容器的某些文件夹映射到宿主机中
    #  可以是JSON数组
    VOLUME  ["/var/log/"]
    
    #  可以直接写
    VOLUME  /var/log
    
    #  可以空格分隔多个
    VOLUME  /var/log  /var/db
    
    • 小结

      • 用VOLUME声明了卷,那么以后对于卷内容的修改会被丢弃,所以一定在 VOLUME 声明之前修改内容
    • 实战:修改宿主机中文件

    上面使用WORKDIR来实现了一步定位到资源文件,但是还是需要进入容器中,依然不是很方便,最好是可以在宿主机中修改容器中的资源文件

    • Dockerfile
    FROM nginx
    #   进入容器的指定目录
    WORKDIR /usr/share/nginx/html/
    
    #   挂载容器文件
    VOLUME  ["/usr/share/nginx/html/"]
    
    • 进入容器


      image.png
    • 查看容器

    docker inspect 056c4dd90dd8
    
    image.png
    • 宿主机中可以查询到容器挂载出来的资源 image.png
    • 默认显示 image.png
    • 通过宿主机修改容器中资源 image.png

    九、USER

    USER 指令设置运行映像时要使用的用户名(或UID,推荐使用UID)以及可选的用户组(或GID,推荐使用GID),以及Dockerfile中USER后面所有RUN、CMD和ENTRYPOINT指令

    USER <user>[:<group>]
    USER <UID>[:<GID>]
    

    十、EXPOSE

    • EXPOSE指令通知 Docker 容器在运行时在指定的网络端口上进行监听。可以指定端口是监听TCP还是UDP,如果未指定协议,则默认值为TCP
    • EXPOSE指令实际上不会发布端口。充当构建镜像的人员与运行容器的人员之间的一种文档,即有关打算发布哪些端口的信息。要在运行容器时实际发布端口,请在docker run 上使用 -p 标志发布并映射一个或多个端口,或使用 -P 标志发布所有公开的端口并将其映射到高阶端口
    EXPOSE <port> [<port>/<protocol>...]
    EXPOSE [80,443] 
    EXPOSE 80/tcp 
    EXPOSE 80/udp
    

    相关文章

      网友评论

        本文标题:06-Dockerfile命令

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