IT评测·应用市场-qidao123.com技术社区

标题: Docker--Docker镜像制作的注意事项 [打印本页]

作者: 一给    时间: 2025-4-9 07:35
标题: Docker--Docker镜像制作的注意事项
Docker 镜像制作 dockerfiles的指令讲解 链接
CMD和ENTRYPOINT

CMDENTRYPOINT 是 Dockerfile 中用于指定容器启动时运行命令的两个指令。它们在功能上有一些相似之处,但也存在紧张区别。
在编辑Dockerfile时,ENTRYPOINT大概CMD命令会自动覆盖之前的ENTRYPOINT大概CMD命令,但是ENTRYPOINTCMD不会相互覆盖。
假如容器启动时通过 docker run 提供了命令行参数,CMD 的内容会被覆盖,而 ENTRYPOINT 的内容可以作为底子命令,并吸收 CMD 或运行参数作为附加参数。
下面通过实例来进行讲解:
编辑Dockerfile1文件
  1. FROM busybox
  2. CMD echo "test cmd1"
  3. CMD echo "TEST CMD1"
复制代码
创建镜像并运行容器
  1. docker build -t cmd:0.1 -f ./Dockerfile1 .
  2. docker run --name cmd1 --rm cmd:0.1
  3. TEST CMD1
复制代码
编辑Dockerfile2文件
  1. FROM busybox
  2. ENTRYPOINT echo "test cmd1"
  3. ENTRYPOINT echo "TEST CMD1"
复制代码
创建镜像并运行容器
  1. docker build -t cmd:0.2 -f ./Dockerfile2 .
  2. docker run --name cmd1 --rm cmd:0.2
  3. TEST CMD1
复制代码
编辑Dockerfile3文件
  1. FROM busybox
  2. ENTRYPOINT echo "test cmd1"
  3. CMD echo "TEST CMD1"
复制代码
创建镜像并运行容器
  1. docker build -t cmd:0.3 -f ./Dockerfile3 .
  2. docker run --name cmd1 --rm cmd:0.3
  3. test cmd1
复制代码
实行指令不会被覆盖,但只是实行一条语句
编辑Dockerfile0文件
  1. FROM ubuntu:latest
  2. ENTRYPOINT ["echo"]
  3. CMD ["Hello from CMD"]
复制代码
启动容器时,默认实行 echo "Hello from CMD"。
假如运行 docker run myimage "Hello from run",输出 Hello from run,由于 CMD 的内容被覆盖,但 ENTRYPOINT 仍然是 echo。
Shell形式和exec形式

exec形式:
  1. ENTRYPOINT ["executable", "param1", "param2"]
复制代码
Shell形式:
  1. ENTRYPOINT command param1 param2
复制代码
当使用shell表现法时,命令行步伐作为sh步伐的子步伐运行;docker用bin/sh -c来调用
当用docker ps 查看时就能看出我们运行的是/bin/sh -c 的命令;这样运行的PID不是1;这也意味着Unix不会吸收任何信号;
exec语法中,没有启动/bin/sh的命令,而是直接运行提供的命令,命令PID是1.
编辑dockerfile4文件
shell模式
  1. FROM ubuntu:22.04
  2. RUN apt-get update -y && apt install -y iputils-ping
  3. CMD ping localhost
复制代码
创建镜像并运行容器:
  1. docker build -t cmd:0.4 -f ./Dockerfile4 .
  2. docker run -d --name cmd1 --rm cmd:0.4
  3. docker ps
复制代码

查看容器可以看到命令为 /bin/sh -c为主步伐
进入容器内进行查看,可以看到PID1是/bin/sh
  1. docker exec -it cmd1 bash
  2. ps -ef
复制代码

编辑dockerfile5文件
exec模式
  1. FROM ubuntu:22.04
  2. RUN apt-get update -y && apt install -y iputils-ping
  3. CMD ["ping","localhost"]
复制代码
创建镜像并运行容器:
  1. docker build -t cmd:0.5 -f ./Dockerfile5 .
  2. docker run -d --name cmd1 --rm cmd:0.5
复制代码
通过docker ps 查看:

进入到容器中查看
  1. docker exec -it cmd1 bash
  2. ps -ef
复制代码

ENTRYPOINT也是一样的操作
组合模式

ENTRYPOINT可以作为默认的命令,CMD指定默认运行参数 ;
也就是说,docker会把CMD的命令拼接到ENTRYPOINT命令后面
编辑Dockerfie6文件内容:
  1. FROM ubuntu:22.04
  2. RUN apt-get update -y && apt install -y iputils-ping
  3. ENTRYPOINT ["/bin/ping","-c","3"]
  4. CMD ["localhost"]
复制代码
  1. docker build -t cmd:0.6 -f ./Dockerfile6 .
  2. docker run --name cmd1 --rm cmd:0.6
  3. PING localhost(localhost (::1)) 56 data bytes
  4. 64 bytes from localhost (::1): icmp_seq=1 ttl=64 time=0.020 ms
  5. 64 bytes from localhost (::1): icmp_seq=2 ttl=64 time=0.032 ms
  6. 64 bytes from localhost (::1): icmp_seq=3 ttl=64 time=0.031 ms
复制代码
可以看到CMD的内容被添加进去了;
CMD参数更换
  1. docker run --name cmd1 --rm cmd:0.6 www.baidu.com
复制代码

善用.dockerignore 文件

.dockerignore 文件是 Docker 构建镜像时的紧张工具,用于指定在构建过程中应忽略的文件和目次。公道使用 .dockerignore 可以显著淘汰镜像体积、加速构建速度,并避免将敏感信息打包到镜像中。
默认情况下,Docker 会将 Dockerfile 地点目次的所有文件和子目次复制到构建上下文(build context)中。假如目次中包罗大量无关文件(如日记文件、暂时文件、IDE 配置文件等),会导致构建上下文过大,从而增长镜像体积。
构建上下文越大,Docker 在构建镜像时须要传输和处理的数据就越多,导致构建时间变长。通过忽略不须要的文件,可以显著缩短构建时间。
假如构建上下文中包罗敏感文件(如 .env、密钥文件、配置文件等),可能会被意外打包到镜像中,导致安全风险。
.dockerignore 文件的语法与 .gitignore 雷同,支持通配符和模式匹配。
每一行定义一个匹配规则,空行和以 # 开头的行会被忽略。
   常见模式
*:匹配任意文件或目次(不包罗目次自己)。
**:匹配任意层级的子目次。
?:匹配单个字符。
[abc]:匹配括号内的任意一个字符。
!:取反,表现不忽略匹配的文件。
  如:
  1. # 忽略所有日志文件
  2. *.log
  3. # 忽略临时文件
  4. *.tmp
  5. temp/
  6. # 忽略特定目录
  7. node_modules/
  8. .git/
  9. # 忽略所有隐藏文件(以.开头的文件)
  10. .*
  11. # 包含特定文件(即使它匹配了其他规则)
  12. !important.txt
复制代码
下面通过实例来验证:
建立dockerfile
  1. FROM centos:7
  2. COPY ./* /
复制代码
编写.dockerignore
  1. *.txt
复制代码
创建几个文件

创建镜像
  1. docker build -t test_ignore:1.0 ./
复制代码
运行容器,然后查看目次内容
  1. docker run  -it test_ignore:1.0
复制代码

发现对应目次后缀txt文件都没有了
镜像的多阶段构建

多阶段构建是 Docker 提供的一种优化镜像构建流程的技能,答应在单个 Dockerfile 中使用多个 FROM 指令,每个 FROM 指令开启一个新的构建阶段。最终镜像只保留最后一个阶段的构建结果,从而大幅减小镜像体积,提拔安全性和性能。
传统构建方式会将所有构建依赖(如编译器、构建工具)和中间产物打包到最终镜像中,导致镜像体积庞大。
构建工具和依赖可能包罗已知漏洞,移除这些工具可以降低攻击面。
将构建逻辑集中在一个 Dockerfile 中,避免维护多个独立的构建脚本。
更小的镜像意味着更快的上传、下载和启动时间。
关键点 :
每个 FROM 指令开启一个新阶段。
阶段可以通过 AS关键字定名,方便后续引用。
使用 COPY --from= < stage > 从其他阶段复制文件。
实例:
编写dockerfile文件:
  1. #第一阶段构建
  2. FROM centos:7 AS basebuilder
  3. ENV VERSION="1.0"
  4. RUN sed -e 's|^mirrorlist=|#mirrorlist=|g' \
  5.     -e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.ustc.edu.cn/centos-vault/centos|g' \
  6.     -i.bak \
  7.     /etc/yum.repos.d/CentOS-Base.repo
  8. WORKDIR /src
  9. COPY demo.c .
  10. RUN yum makecache && yum install gcc -y
  11. RUN gcc -o demo demo.c && \
  12.     rm -f demo.c && \
  13.     yum remove -y gcc
  14. CMD ["/src/demo"]
复制代码
我们将以这个镜像作为第一阶段的构建,编写第一阶段的Dockerfile,所占内存:

编写第二阶段的Dockerfile:
  1. #第一阶段构建
  2. FROM centos:7 AS basebuilder
  3. ENV VERSION="1.0"
  4. RUN sed -e 's|^mirrorlist=|#mirrorlist=|g' \
  5.     -e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.ustc.edu.cn/centos-vault/centos|g' \
  6.     -i.bak \
  7.     /etc/yum.repos.d/CentOS-Base.repo
  8. WORKDIR /src
  9. COPY demo.c .
  10. RUN yum makecache && yum install gcc -y
  11. RUN gcc -o demo demo.c && \
  12.     rm -f demo.c && \
  13.     yum remove -y gcc
  14. CMD ["/src/demo"]
  15. # 第二阶段构建FROM CentOS7# 拷贝第一阶段天生的可实行步伐COPY --from=basebuilder /src/demo /src/demo# 运行可实行步伐CMD ["/src/demo"]
复制代码
domo文件:
  1. #include <stdio.h>
  2. int main()
  3. {
  4.     printf("Test commit image\n");
  5.     return 0;
  6. }
复制代码
创建镜像及运行容器
  1. docker build -t multi:0.2 .
  2. docker run --name multi --rm multi:0.2
  3. Test commit image
复制代码
查看镜像巨细:

像我们这种只是跑一个可实行步伐文件而已,假如我们将第二阶段根本镜像换成busybox的话,那么所占内存会更小:

  1. docker build -t multi:0.3 .
  2. docker run --name multi --rm multi:0.3
  3. Test commit image
复制代码

公道利用缓存

Docker 构建镜像时,默认会利用缓存机制加速构建过程:
假如某层(RUN、COPY、ADD等指令)的输入未变革,Docker 会直接复用缓存结果,跳过重复实行。
上风:显著淘汰构建时间,尤其是在依赖较多或构建步骤复杂时。
Docker 镜像由多个层(Layer)组成,每层对应一个构建指令。
缓存以层为单位存储,只有当某层的输入(如文件内容、环境变量)变革时,该层及其后续层才会失效。
缓存失效规则
   COPY/ADD 指令
  
  RUN 指令
  
  环境变量
  
  以是要利用好缓存的规则

实例:
利用c++制作的镜像Dockerfile文件进利用用:
dockerfile:
  1. FROM centos:7 AS basebuilder
  2. ENV VERSION="1.0"
  3. RUN sed -e 's|^mirrorlist=|#mirrorlist=|g' \
  4.     -e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.ustc.edu.cn/centos-vault/centos|g' \
  5.     -i.bak \
  6.     /etc/yum.repos.d/CentOS-Base.repo
  7. RUN yum makecache && yum install gcc -y
  8. WORKDIR /src
  9. COPY demo.c .
  10. RUN gcc -o demo demo.c && \
  11.     rm -f demo.c && \
  12.     yum remove -y gcc
  13. CMD ["/src/demo"]
复制代码
demo.c
  1. #include <stdio.h>
  2. int main()
  3. {
  4.     printf("Test CACHE image\n");
  5.     return 0;
  6. }
复制代码
第一次创建镜像
  1. docker build -t cache:1.0 .
复制代码
花费了40s的时间

第二次创建镜像之前,我们修改下demo.c:

再次创建镜像
  1. docker build -t cache:2.0 .
复制代码

会发现这次创建时间还是许多,这是由于demo.c的改变,影响了Dockerfile文件内容COPY demo.c . 后面全部内容,后面的内容都要进行重新创建;以是,安排好我们的实行语句次序非常紧张,将不常修改的语句放到前头,常常修改的语句放到反面;这里是我们安装gcc影响到了,但是对于我们来说又没有常常修改,以是我们将这条语句放到前面的位置
再次创建镜像
  1. docker build -t cache:3.0 .                                                                                         
  2. [+] Building 42.4s (11/11) FINISHED
复制代码
由于我们改变了实行语句的次序,以是须要重修
再次修改demo.c文件再创建镜像

  1. docker build -t cache:4.0 .                                                                                         
  2. [+] Building 1.9s (11/11) FINISHED
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4