dockerfile

举报
yd_224301282 发表于 2023/07/24 19:25:50 2023/07/24
【摘要】 dockerfile介绍Dockerfile是一种被Docker程序解释执行的脚本,由一条条的命令组成,每条命令对应linux下面的一条命令,Docker程序将这些Dockerfile指令翻译成真正的linux命令,其有自己的书写方式和支持的命令,Docker程序读取Dockerfile并根据指令生成Docker镜像,相比手动制作镜像的方式,Dockerfile更能直观的展示镜像时怎么产生的...

dockerfile

介绍

  • Dockerfile是一种被Docker程序解释执行的脚本,由一条条的命令组成,每条命令对应linux下面的一条命令,Docker程序将这些Dockerfile指令翻译成真正的linux命令,其有自己的书写方式和支持的命令,Docker程序读取Dockerfile并根据指令生成Docker镜像,相比手动制作镜像的方式,Dockerfile更能直观的展示镜像时怎么产生的,有了Dockerfile,当后期有额外的需求时,只要在之前的Dockerfile添加或者修改相应的命令即可重新生成新的docker镜像,避免了重复手动制作镜像。

  • dockerfile文件说明

    • 每一行以Dockerfile的指令开头,指令不区分大小写,但是惯例使用大写
    • 使用#开始作为注释
    • 每一行只支持一条指令,每条指令可以携带多个参数
    • 指令按文件的顺序从上至下进行执行
    • 每个指令的执行会生成一个新的镜像层,为了减少分层和镜像大小,仅可能将多条指令合并成一条指令
    • 一般需要多次执行dockerfile才能制作一个满意的镜像,每次执行Dockerfile都按顺序执行,从头开始,上次制作镜像时已经执行过的指令会被缓存,不需要重新执行,如果后续有一行新的指令没有被执行过,其往后的指令都将会重新执行,所以为了加速镜像制作,通常将最常变化的指令放在Dockerfile文件的最后面
  • dockerfile的相关指令

    • FROM:就是指定基础镜像,此指令通常必须放在Dockerfile文件第一个指令,后续的指令都是运行于此基准镜像所提供的运行环境

      • FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
        FROM  nginx:1.0
        
    • 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."
        
    • RUN:用来在构建镜像阶段需要在FROM指定镜像中执行的shell命令(FROM指定的镜像必须支持这个shell)

      • shell格式:RUN /bin/bash -c ls
      • exec格式:RUN ["/bin/bash" , “-c” , “ls”]
    • ENV:设置环境变量,可以被后续指令通过 K E Y KEY或 {KEY}进行引用,并在容器运行时保持

      • ENV <key>=<value>
        ENV WORK_DIR=/app
        
    • COPY:复制本地宿主机的文件到容器内

      • 不能复制上下文之外的文件(docker build命令执行的目录为上下文)

      • 如果是目录,只复制目录中的内容,而非目录本身

      • COPY checkredis.py .			把checkredis.py复制到WORKDIR目录中
        COPY check.log /testdir/ 		把上下文中的check.log复制到/testdir目录下
        COPY nickdir .					把nickdir目录中的内容复制到WORKDIR目录中,不复制目录本身
        
    • ADD:该命令可认为是增强版的COPY,不仅支持COPY,还支持自动解压。可以将指定的文件复制到容器内

      • 不能复制上下文之外的文件(docker build命令执行的目录为上下文)

      • 可以是Dockerfile所在目录的一个相对路径,也可以是一个URL,还可以是一个tar文件会自动解压

      • 如果是目录,只复制目录中的内容,而非目录本身

      • 如果是一个URL,下载后的文件权限自动设置为600

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

      • 如果是本地文件系统上的打包文件,如:gz,bz2,xz,它将被解压,但是通过URL获取到的tar文件将不会自动展开

      • 如果有多个或其间接使用了通配符,则必须是一个以/结尾的目录路径,如果不以/结尾,则其被视作一个普通文件

      • ADD  http://example.com/big.tar.xz  /usr/src/things/
        ADD  nickdir.tar.gz  .
        
    • CMD:启动容器命令或者参数

      • 如果docker run没有指定任何的执行命令或者Dockerfile里也没有ENTRYPOINT,那么启动容器时就会执行CMD指定的默认命令

      • 每个Dockerfile只能有一条CMD命令。如果指定了多条,只有最后一条被执行

      • 如果用户启动容器时用docker run 指定运行命令,则会覆盖CMD指定的命令

      • CMD语法

        • #exec形式
          ENTRYPOINT  [ "executable" , "param1", "param2" ]
          #shell形式
          ENTRYPOINT  command  param1  param2
          
    • ENTRYPOINT:功能类似于CMD,配置容器启动后执行的命令及参数

      • ENTRYPOINT不能被docker run提供的参数覆盖,而是追加,即如果docker run命令有参数,那么参数全部都会作为ENTTRYPOINT的参数

      • 如果docker run后面没有额外参数,但是Dockerfile中的CMD里有,即Dockerfile中即有CMD也有ENTRYPOINT,那么CMD全部内容作为ENTRYPOINT的参数

      • 如果docker run后面有额外的参数,同时Dockerfile中既有CMD也有ENTRYPOINT,那么docker run后面的参数覆盖掉CMD参数内容,最终作为ENTRYPOINT的参数

      • 可以通过docker run --entrypoint 指令覆盖dockerfile里指定的ENTRYPOINT,如

        • docker run -it --entrypoint /srv/java/jdk/bin/java -jar /tmp/sms.jar
          
      • 每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个生效

      • ENTRYPOINT语法

        • #exec形式
          ENTRYPOINT  [ "executable" , "param1", "param2" ]
          ENTRYPOINT ["java","-jar","app.jar"]
          #shell形式
          ENTRYPOINT  command  param1  param2
          
    • ARG:构建参数,在build阶段指定变量和ENV不同的是,容器运行时不会存在这些环境变量

    • VOLUME:匿名卷

      • 将容器中指定的目录挂载到宿主机上,宿主机目录不可指定,会自动生成。docker run -v 参数指定的容器目录与宿主机目录的具体路径都可以指定

      • VOLUME ["/data1","/data2"]
        
    • EXPOSE:暴露端口,指定服务端的容器需要对外暴露的端口号,以实现容器与外部通信

      • 这个参数用处不大,不指定也行,在docker run时使用-p 指定端口就可以了,EXPOSE的主要用处就是对于以后交接的运维人员进行端口提示
    • WORKDIE:指定工作目录,为后续的RUN、CMD、ENTRYPOINT指定工作目录,当容器运行后,进入容器内WORKDIR指定的默认目录,当该目录不存在时会自动创建

      • WORKDIR /path/to/workdir
        
    • USER:指定当前用户,dockerfile后续的RUN CMD ENTRYPOINT都将使用该用户,指定的用户需要在当前系统已经存在

      • USER  <user>[:<group>]USER  <UID>[:<GID>]
        
    • SHELL:可以指定 RUN、ENTRYPOINT、CMD 指令的 shell,Linux 中默认为 ["/bin/sh", “-c”]

      • SHELL   ["/bin/sh", "-c"] 
        

CDM和ENTRYPOINT的shell和exec模式

  • CMD 和 ENTRYPOINT 指令都支持 exec 模式和 shell 模式的写法,所以要理解 CMD 和 ENTRYPOINT 指令的用法,就得先区分 exec 模式和 shell 模式。这两种模式主要用来指定容器中的不同进程为 1 号进程。

  • exec模式

    • 使用 exec 模式时,容器中的任务进程就是容器内的 1 号进程,exec 模式的特点是不会通过 shell 执行相关的命令,所以像 $HOME 这样的环境变量是取不到的:

    • FROM ubuntu
      CMD [ "top" ]
      
    • img

  • shell模式

    • 使用 shell 模式时,docker 会以 /bin/sh -c “task command” 的方式执行任务命令。也就是说容器中的 1 号进程不是任务进程而是 bash 进程

    • FROM ubuntu
      CMD top
      
    • img

dockerfile使用exec模式的重要性

  • 信号是一种进程间通信的形式。一个信号就是内核发送给进程的一个消息,告诉进程发生了某种事件。当一个信号被发送给一个进程后,进程会立即中断当前的执行流并开始执行信号的处理程序(这么说不太准确,信号是在特定的时机被处理)。如果没有为这个信号指定处理程序,就执行默认的处理程序。
  • 进程需要为自己感兴趣的信号注册处理程序,比如为了能让程序优雅的退出(接到退出的请求后能够对资源进行清理)一般程序都会处理 SIGTERM 信号。与 SIGTERM 信号不同,SIGKILL 信号会粗暴的结束一个进程。因此我们的应用应该实现这样的目录:捕获并处理 SIGTERM 信号,从而优雅的退出程序。如果我们失败了,用户就只能通过 SIGKILL 信号这一终极手段了。除了 SIGTERM 和 SIGKILL ,还有像 SIGUSR1 这样的专门支持用户自定义行为的信号。
  • Docker 的 stop 和 kill 命令都是用来向容器发送信号的。注意,只有容器中的 1 号进程能够收到信号,这一点非常关键!docker stop 命令会首先发送 SIGTERM 信号,并等待容器优雅的结束。如果发现容器没有结束(用户可以指定等待的时间),就再发送一个 SIGKILL 信号强行结束容器。
  • 在dockerfile的ENTRYPOINT下的exec模式时,exec的命令就是容器中的一号进程,外部发给容器的信号是可以被命令收到的。但是如果使用ENTRYPOINT的shell模式,则命令不是容器中的1 号进程,则外部发送的信号命令收不到,而是实行命令的bash收到了,bash收到信号后如果没有相应的处理,则docker stop就会发送kill -9 粗暴的结束进程
  • image-20230724162144792

docker build

docker build .		在当前目录进行构建

https://www.cnblogs.com/sparkdev/p/8461576.html

https://www.cnblogs.com/sparkdev/p/7598590.html

https://www.cnblogs.com/sparkdev/p/6659629.html

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。