一给 发表于 2025-4-9 07:35:15

Docker--Docker镜像制作的注意事项

Docker 镜像制作 dockerfiles的指令讲解 链接
CMD和ENTRYPOINT

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

exec形式:
ENTRYPOINT ["executable", "param1", "param2"]
Shell形式:
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模式
FROM ubuntu:22.04
RUN apt-get update -y && apt install -y iputils-ping
CMD ping localhost
创建镜像并运行容器:
docker build -t cmd:0.4 -f ./Dockerfile4 .
docker run -d --name cmd1 --rm cmd:0.4
docker ps
https://i-blog.csdnimg.cn/direct/ef7268bd99f5412d8db5032fa0e70894.png
查看容器可以看到命令为 /bin/sh -c为主步伐
进入容器内进行查看,可以看到PID1是/bin/sh
docker exec -it cmd1 bash
ps -ef
https://i-blog.csdnimg.cn/direct/070045581e7e4c8db2b3c84cfaa5ec3d.png
编辑dockerfile5文件:
exec模式
FROM ubuntu:22.04
RUN apt-get update -y && apt install -y iputils-ping
CMD ["ping","localhost"]
创建镜像并运行容器:
docker build -t cmd:0.5 -f ./Dockerfile5 .
docker run -d --name cmd1 --rm cmd:0.5
通过docker ps 查看:
https://i-blog.csdnimg.cn/direct/7e087b08ce8541c898a59e6ad4ce6b0e.png
进入到容器中查看
docker exec -it cmd1 bash
ps -ef
https://i-blog.csdnimg.cn/direct/7fb0ddf3fcef4151ab265e6acc909a89.png
ENTRYPOINT也是一样的操作
组合模式

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

.dockerignore 文件是 Docker 构建镜像时的紧张工具,用于指定在构建过程中应忽略的文件和目次。公道使用 .dockerignore 可以显著淘汰镜像体积、加速构建速度,并避免将敏感信息打包到镜像中。
默认情况下,Docker 会将 Dockerfile 地点目次的所有文件和子目次复制到构建上下文(build context)中。假如目次中包罗大量无关文件(如日记文件、暂时文件、IDE 配置文件等),会导致构建上下文过大,从而增长镜像体积。
构建上下文越大,Docker 在构建镜像时须要传输和处理的数据就越多,导致构建时间变长。通过忽略不须要的文件,可以显著缩短构建时间。
假如构建上下文中包罗敏感文件(如 .env、密钥文件、配置文件等),可能会被意外打包到镜像中,导致安全风险。
.dockerignore 文件的语法与 .gitignore 雷同,支持通配符和模式匹配。
每一行定义一个匹配规则,空行和以 # 开头的行会被忽略。
   常见模式
*:匹配任意文件或目次(不包罗目次自己)。
**:匹配任意层级的子目次。
?:匹配单个字符。
:匹配括号内的任意一个字符。
!:取反,表现不忽略匹配的文件。
如:
# 忽略所有日志文件
*.log

# 忽略临时文件
*.tmp
temp/

# 忽略特定目录
node_modules/
.git/

# 忽略所有隐藏文件(以.开头的文件)
.*

# 包含特定文件(即使它匹配了其他规则)
!important.txt
下面通过实例来验证:
建立dockerfile
FROM centos:7

COPY ./* /
编写.dockerignore
*.txt
创建几个文件
https://i-blog.csdnimg.cn/direct/72432b1b11bc4157a197e848822a8dc1.png
创建镜像
docker build -t test_ignore:1.0 ./
运行容器,然后查看目次内容
docker run-it test_ignore:1.0
https://i-blog.csdnimg.cn/direct/3c8451e5be3a4f3cb2c2e606c4c78f44.png
发现对应目次后缀txt文件都没有了
镜像的多阶段构建

多阶段构建是 Docker 提供的一种优化镜像构建流程的技能,答应在单个 Dockerfile 中使用多个 FROM 指令,每个 FROM 指令开启一个新的构建阶段。最终镜像只保留最后一个阶段的构建结果,从而大幅减小镜像体积,提拔安全性和性能。
传统构建方式会将所有构建依赖(如编译器、构建工具)和中间产物打包到最终镜像中,导致镜像体积庞大。
构建工具和依赖可能包罗已知漏洞,移除这些工具可以降低攻击面。
将构建逻辑集中在一个 Dockerfile 中,避免维护多个独立的构建脚本。
更小的镜像意味着更快的上传、下载和启动时间。
关键点 :
每个 FROM 指令开启一个新阶段。
阶段可以通过 AS关键字定名,方便后续引用。
使用 COPY --from= < stage > 从其他阶段复制文件。
实例:
编写dockerfile文件:
#第一阶段构建
FROM centos:7 AS basebuilder

ENV VERSION="1.0"

RUN sed -e 's|^mirrorlist=|#mirrorlist=|g' \
    -e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.ustc.edu.cn/centos-vault/centos|g' \
    -i.bak \
    /etc/yum.repos.d/CentOS-Base.repo

WORKDIR /src

COPY demo.c .

RUN yum makecache && yum install gcc -y

RUN gcc -o demo demo.c && \
    rm -f demo.c && \
    yum remove -y gcc

CMD ["/src/demo"]
我们将以这个镜像作为第一阶段的构建,编写第一阶段的Dockerfile,所占内存:
https://i-blog.csdnimg.cn/direct/515b377177854676beb003be15a591b0.png
编写第二阶段的Dockerfile:
#第一阶段构建
FROM centos:7 AS basebuilder

ENV VERSION="1.0"

RUN sed -e 's|^mirrorlist=|#mirrorlist=|g' \
    -e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.ustc.edu.cn/centos-vault/centos|g' \
    -i.bak \
    /etc/yum.repos.d/CentOS-Base.repo

WORKDIR /src

COPY demo.c .

RUN yum makecache && yum install gcc -y

RUN gcc -o demo demo.c && \
    rm -f demo.c && \
    yum remove -y gcc

CMD ["/src/demo"]
# 第二阶段构建FROM CentOS7# 拷贝第一阶段天生的可实行步伐COPY --from=basebuilder /src/demo /src/demo# 运行可实行步伐CMD ["/src/demo"] domo文件:
#include <stdio.h>

int main()
{
    printf("Test commit image\n");
    return 0;
}
创建镜像及运行容器
docker build -t multi:0.2 .
docker run --name multi --rm multi:0.2
Test commit image
查看镜像巨细:
https://i-blog.csdnimg.cn/direct/4eb28a0ec7504bceb8bc6f39fa18f76f.png
像我们这种只是跑一个可实行步伐文件而已,假如我们将第二阶段根本镜像换成busybox的话,那么所占内存会更小:
https://i-blog.csdnimg.cn/direct/78eef1f046594fe293eb07ccfa69355e.png
docker build -t multi:0.3 .
docker run --name multi --rm multi:0.3
Test commit image
https://i-blog.csdnimg.cn/direct/9550d89ff39d405a962909d0271eebcd.png
公道利用缓存

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


[*]假如源文件内容变革,缓存失效。
[*]假如仅文件名或目次结构变革,但内容未变,缓存可能仍有用(取决于文件哈希值)。
RUN 指令:


[*]假如依赖的上一层缓存失效,则当前层的缓存也会失效。
环境变量:


[*]ARG 和 ENV 的变革会导致后续层缓存失效。
以是要利用好缓存的规则


[*]将不常变革的指令放在前面,常变革的指令放在后面
[*]避免在关键层使用 COPY
[*]使用 ARG 参数控制构建环境
实例:
利用c++制作的镜像Dockerfile文件进利用用:
dockerfile:
FROM centos:7 AS basebuilder

ENV VERSION="1.0"

RUN sed -e 's|^mirrorlist=|#mirrorlist=|g' \
    -e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.ustc.edu.cn/centos-vault/centos|g' \
    -i.bak \
    /etc/yum.repos.d/CentOS-Base.repo

RUN yum makecache && yum install gcc -y

WORKDIR /src

COPY demo.c .

RUN gcc -o demo demo.c && \
    rm -f demo.c && \
    yum remove -y gcc

CMD ["/src/demo"]
demo.c
#include <stdio.h>

int main()
{
    printf("Test CACHE image\n");
    return 0;
}
第一次创建镜像
docker build -t cache:1.0 .
花费了40s的时间
https://i-blog.csdnimg.cn/direct/bb70d784e7744460bdead65f57cc4e4f.png
第二次创建镜像之前,我们修改下demo.c:
https://i-blog.csdnimg.cn/direct/74d81674187a49db8301785bc597d753.png
再次创建镜像
docker build -t cache:2.0 .
https://i-blog.csdnimg.cn/direct/35e2bcd051c04ef79617d3a6864c150f.png
会发现这次创建时间还是许多,这是由于demo.c的改变,影响了Dockerfile文件内容COPY demo.c . 后面全部内容,后面的内容都要进行重新创建;以是,安排好我们的实行语句次序非常紧张,将不常修改的语句放到前头,常常修改的语句放到反面;这里是我们安装gcc影响到了,但是对于我们来说又没有常常修改,以是我们将这条语句放到前面的位置
再次创建镜像
docker build -t cache:3.0 .                                                                                       
[+] Building 42.4s (11/11) FINISHED
由于我们改变了实行语句的次序,以是须要重修
再次修改demo.c文件再创建镜像
https://i-blog.csdnimg.cn/direct/918b3efff0084b54b7dd12ebd9b0354c.png
docker build -t cache:4.0 .                                                                                       
[+] Building 1.9s (11/11) FINISHED

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Docker--Docker镜像制作的注意事项