百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Dockerfile优化有技巧,Docker镜像构建提速10倍!

off999 2025-04-06 19:58 112 浏览 0 评论

本文主要记录了自己通过查阅相关资料,一步步排查问题,最后通过优化Docerfile文件将Docker镜像构建从十几分钟降低到1分钟左右,效率提高了10倍左右。


一、概述


最近在开发python应用程序,在部署应用的时候发现构建镜像过程十分缓慢,极大影响开发效率。既然遇到了问题就不要逃避,而应该尝试解决一下。本文主要记录了自己通过查阅相关资料,一步步排查问题,最后通过优化Dockerfile文件将docker镜像构建从十几分钟降低到1分钟左右,效率提高了10倍左右。


本文通过如下几个部分进行介绍:

  • 现状:简单介绍一下未优化前的情况;
  • 优化效果:简单介绍优化后的情况;
  • 分析过程:介绍如何分析镜像构建存在的问题;
  • 优化过程:介绍如何通过优化Dockerfile提高镜像构建效率;
  • 优化总结:最后总结镜像构建的几个优化方法;


通过本文的学习,你将有如下收获:

1、了解镜像构建优化的过程。

2、了解一些常用的镜像构建优化的技巧。


二、优化前效果



未优化前可以看到镜像构建耗时16分钟,构建完成后镜像大小约8G,使用的Dockerfile文件如下:


FROM reg.docker.alibaba-inc.com/aci-images/python-service:3.8.0-63928922


# init folder
RUN mkdir -p /home/admin/logs && mkdir -p /home/admin/bin && mkdir -p /home/admin/conf && mkdir -p /home/admin/nginx && mkdir -p /home/admin/.maxhub/env_helper_util/zeta-local-env


# install zeta
RUN pushd /home/admin/.maxhub/env_helper_util/zeta-local-env && \
    wget https://artifacts.antgroup-inc.cn/artifact/repositories/softwares-common/antcode/zeta/0.7.9/zeta-linux-amd64-0.7.9.sh -O zeta-release.sh && \
    chmod +x zeta-release.sh && \
    ./zeta-release.sh --prefix=/usr/local && \
    popd


# init env and install software
COPY conf/docker/build.yaml /root/
RUN python3.10 -m pip install -U antimgbuilder -i https://pypi.antfin-inc.com/simple && \
    python3.10 -m antimgbuilder --config-file /root/build.yaml


# copy source file
# COPY --chown=admin:admin mydemo /home/admin/release/mydemo
COPY --chown=admin:admin aml_core /home/admin/release/aml_core
COPY --chown=admin:admin backend /home/admin/release/backend


# install  requirements.txt
COPY --chown=admin:admin requirements.txt /home/admin/release/
RUN python3.10 -m venv /home/admin/run && \
    . /home/admin/run/bin/activate && \
    python3.10 -m pip install -i https://pypi.antfin-inc.com/simple-remote --upgrade pip &&\
    python3.10 -m pip install -i https://pypi.antfin-inc.com/simple -r /home/admin/release/requirements.txt


# copy scripts
COPY --chown=admin:admin conf/docker/scripts/admin /home/admin
COPY --chown=admin:admin conf/nginx /home/admin/nginx


# 最后确保admin目录下文件权限
RUN chown admin:admin -R /home/admin


RUN chmod a+xw /home/admin/bin/fetch_ollama.sh /tmp


三、优化后效果



优化后可以看到镜像构建时间为1分钟左右,镜像大小约5G,使用的Dockerfile如下:


# 第一阶段:下载依赖
FROM reg.docker.alibaba-inc.com/antfin-sqa/amlregservermodel-dev:20241016125401_b0296dab as builder


# install  requirements.txt
COPY --chown=admin:admin requirements.txt /home/admin/release/
RUN python3.10 -m venv /home/admin/run && \
    . /home/admin/run/bin/activate && \
    python3.10 -m pip install -i https://pypi.antfin-inc.com/simple-remote --upgrade pip &&\
    python3.10 -m pip install -i https://pypi.antfin-inc.com/simple -r /home/admin/release/requirements.txt --no-cache-dir




# 第二阶段:构建应用程序镜像
FROM reg.docker.alibaba-inc.com/aci-images/python-service:3.8.0-63928922


# init folder
RUN mkdir -p /home/admin/logs && mkdir -p /home/admin/bin && mkdir -p /home/admin/conf && mkdir -p /home/admin/nginx && mkdir -p /home/admin/.maxhub/env_helper_util/zeta-local-env


# install zeta
RUN pushd /home/admin/.maxhub/env_helper_util/zeta-local-env && \
    wget https://artifacts.antgroup-inc.cn/artifact/repositories/softwares-common/antcode/zeta/0.7.9/zeta-linux-amd64-0.7.9.sh -O zeta-release.sh && \
    chmod +x zeta-release.sh && \
    ./zeta-release.sh --prefix=/usr/local && \
    rm -f zeta-release.sh && \
    popd


# install virtualenv and uvicorn
RUN python3.10 -m venv /home/admin/run && \
    . /home/admin/run/bin/activate && \
    python3.10 -m pip install -i https://pypi.antfin-inc.com/simple-remote --upgrade pip &&\
    python3.10 -m pip install -i https://pypi.antfin-inc.com/simple uvicorn --no-cache-dir


# init env and install software
COPY conf/docker/build.yaml /root/
RUN python3.10 -m pip install -U antimgbuilder -i https://pypi.antfin-inc.com/simple && \
    python3.10 -m antimgbuilder --config-file /root/build.yaml




# copy scripts
COPY --chown=admin:admin conf/docker/scripts/admin /home/admin
COPY --chown=admin:admin conf/nginx /home/admin/nginx
COPY --chown=admin:admin aml_core /home/admin/release/aml_core


RUN chmod a+xw /home/admin/bin/fetch_ollama.sh /tmp


# 从第一阶段复制下载的依赖到第二阶段
COPY --from=builder /home/admin/run/lib/python3.10/site-packages/ /home/admin/run/lib/python3.10/site-packages/


# copy source file
COPY --chown=admin:admin backend /home/admin/release/backend


四、分析过程


1、镜像构建耗时分析


分析优化前的镜像构建构成,找到最耗时的阶段,进入镜像构建任务详情页:



点击 image-build-3 找到耗时最长的指令:



可以看到在指令:

COPY --chown=admin:admin conf/docker/scripts/admin /home/admin

的前一步耗时达到了 10 分钟左右,对照着 Dockerfile 文件可以看到,是下面下载依赖比较耗时。



由于构建出来的镜像比较大,导致推送镜像耗时约:4分钟



镜像构建耗时分析总结:

1)从构建的日志中可以看到是下载依赖比较耗时约:10 分钟。

2)并且前面的指令缓存失效, 则随后指令构建的镜像都不再使用缓存导致耗时增加。

3)构建出来的镜像比较大,导致推送镜像耗时约:4分钟。


2、镜像构建体积较大分析


从前面的Dockfile文件中可以看到,使用的基础镜像是:


reg.docker.alibaba-inc.com/aci-images/python-service:3.8.0-63928922,拉取该镜像,查看基础镜像的体积:



可以看到该镜像的大小是:2.33G


我们进入Docker容器,查看下载依赖的大小以及缓存的大小,下载依赖的缓存目录一般是 /root/.cache/pip:



镜像构建体积较大分析总结:


1)基础镜像体积较大:2.33G。


2)安装的依赖较大,并且下载依赖时默认开启了缓存,导致占用更多的内存空间约:3.1G(包括下载的依赖和缓存占用:2.6G + 729M )。


为什么使用 pip install 安装依赖时没有添加 --no-cache-dir 参数会导致占用的内存更多?


如果在使用 pip install 安装依赖时没有添加 --no-cache-dir 参数,会导致缓存目录中的文件不断增加,占用更多的内存空间。每次使用 pip install 安装依赖时,pip 会默认将下载的依赖包保存在缓存目录 /root/.cache/pip 中,如果没有添加 --no-cache-dir 参数,pip 会在安装依赖时从缓存目录中检查已有的依赖包,如果有相同的包就会直接使用缓存中的包,而不是重新下载。因此,随着时间的推移,缓存目录中会存放越来越多的依赖包,占用更多的内存空间。


为了避免占用更多的内存空间,可以在使用 pip install 安装依赖时添加 --no-cache-dir 参数,这样将禁用缓存,使得每次安装依赖都会重新下载依赖包,从而避免占用更多的内存空间。


3、 使用 docker history 分析


接下来我们使用 docker history 进行分析。


docker history :用于查看 Docker 镜像的构建历史,显示每一层的提交信息,包括镜像 ID、创建人、创建时间和指令。这个命令可以帮助用户理解镜像是如何构建的,了解每个操作对镜像大小的影响,以及对镜像进行优化和精简。通过查看镜像的构建历史,用户可以更好地理解和管理镜像,提高镜像的性能和安全性。


下载镜像到本地或者在本地构建未优化的Dockerfile镜像,使用下面的命令构建镜像:


docker build -f conf/docker/Dockerfile  -t amlservermodel:latest .


使用下面的命令分析镜像,可以看到各个操作对镜像大小的影响如下:


docker history amlservermodel:latest



使用 docker history 分析镜像总结,占用镜像体积较大的两个层是:


1)下载依赖占用约:3.18G(包括下载的依赖和缓存)。


2)给目录设置权限:


在构建docker镜像时,Dockerfile文件中使用指令:RUN chown admin:admin -R /home/admin,为什么会导致镜像体积变大?


这条指令会导致镜像体积变大的原因是,每一条指令在Dockerfile中都会创建一个新的镜像层。当在Dockerfile中使用RUN chown命令时,会创建一个新的镜像层,其中包含了文件权限的更改。这意味着原本的文件和目录仍然存在于之前的镜像层中,而新的镜像层只是在其基础上进行了更改。因此,即使在新的镜像层中删除了一些文件或更改了文件权限,但之前的镜像层仍然包含了这些文件,导致镜像体积变大。


为了避免镜像体积变大,可以在Dockerfile中尽量减少使用RUN指令,或者在同一条RUN指令中一次性执行多个操作,以减少创建的镜像层数。也可以在构建镜像的过程中清理不必要的文件和缓存,以减小镜像的体积。


五、优化过程


1、优化方案


在进行优化之前,我们需要了解一些docker镜像的构建原则:


1)动静分离原则


我们应该把变化最少的部分放在 Dockerfile 的前面,这样可以充分利用镜像缓存。


每条指令只要前面的指令缓存失效, 则随后指令构建的镜像都不再使用缓存。


对应COPY和ADD文件会检验文件的校验和, 如果发现改变则缓存失效。


2)多阶段构建


Docker多阶段构建镜像的原理是利用多个Docker容器来处理不同的构建阶段,并将最终构建产物传递给下一个容器。每个阶段可以定义自己的基础镜像、依赖和构建执行环境,使得镜像的构建过程更加灵活和高效。


多阶段构建镜像可以降低最终镜像的体积的原因包括以下几点:


优化构建产物:多阶段构建可以在不同的阶段处理不同的构建任务,比如编译、打包、测试等,从而避免将构建产物暴露给最终镜像,减小了最终镜像的体积。


移除构建环境:多阶段构建可以将构建时用到的工具、依赖等移除,只将必要的产物传递到最终镜像中,避免了构建环境对最终镜像的影响,减小了最终镜像的体积。


优化基础镜像:多阶段构建可以根据需要选择不同的基础镜像,每个阶段可以选择适合自己需求的基础镜像,从而避免了不必要的依赖和工具被打包到最终镜像中,减小了最终镜像的体积。


综上所述,多阶段构建镜像可以将构建过程分解成多个阶段,根据需要进行优化,避免了不必要的依赖和工具被打包到最终镜像中,从而降低了最终镜像的体积。


2、优化分析


通过前面的分析,我们做出如下优化:


1)构建耗时优化


通过多阶段构建的方式,可以并行的处理不同阶段的构建,只将必要的产物传递到最终镜像,为了提高下载依赖的效率,我们还可以将项目中使用的依赖提前下载好,构建在第一阶段或者基础镜像中,避免每次重新下载全部依赖。我的优化方案如下:


使用多阶段构建,第一阶段下载依赖,第二阶段构建应用程序镜像。


对于第一阶段下载依赖,我将应用程序需要的依赖构建在基础镜像中,避免重新下载全部依赖,如果依赖文件 requirements.txt有变化,则会重新下载依赖,并且和第二阶段的构建是并行进行,任然是可以提高构建效率的,我的修改如下:



最后将下载的依赖从第一阶段复制到第二阶段,因为应用程序会频繁修改,所以将应用程序的代码放在了Dockerfile文件的最后,将不经常变化的内容放在Dockerfile文件前面,可以充分利用镜像的缓存提高效率,修改后的Dockerfile文件如下:



我们查看优化后的构建过程如下:



2)镜像体积优化


针对前面的分析,当前案例中镜像体积较大的原因有如下几点:

  • 基础镜像较大;
  • 安装的依赖较大,并且开启了缓存;
  • 使用RUN chown 指令导致镜像较大;
  • 由于镜像构建中发现有很多指令,构建了很多层,导致镜像体积变大;


针对的优化方案:

  • 基础镜像较大我们可以选择较小的基础镜像,可以在 蚂蚁的基础镜像中查找对应的基础镜像;
  • 安装依赖时使用 pip install --no-cache-dir 关闭缓存;
  • 移除 RUN chown指令,因为在这里可以针对特定的文件或者文件夹指定就行,不需要对所有的目录修改权限;
  • 合并多个RUN指令,减少镜像的层数,进而减少镜像的体积;


最后通过针对性的优化,镜像体积减小到原来的一半,本来想找一个体积更小的基础镜像,但是在基础镜像库中没有找到合适的版本,并且通过前面的一系列优化,镜像的构建时间以及可以达到秒级了,所以后续有需要再自定义一个合适的基础镜像。


六、构建缓存失效


构建镜像时,Docker 会逐步执行 Dockerfile 中的指令,并按指定的顺序执行每条指令。对于每条指令, 构建器都会检查是否可以重用构建缓存中的指令。


1、一般规则


构建缓存失效的基本规则如下:

  • 构建器首先检查基础镜像是否已缓存。随后的每个指令都会与缓存的层进行比较,如果没有缓存的层与指令完全匹配,则缓存将失效。
  • 在大多数情况下,将 Dockerfile 指令与相应的缓存层进行比较就足够了,但是有些指令需要额外的检查和解释。
  • 对于ADD和COPY指令以及RUN带有绑定挂载的指令(RUN --mount=type=bind),构建器会根据文件元数据计算缓存校验和,以确定缓存是否有效。在缓存查找期间,如果涉及的任何文件的文件元数据发生更改,则缓存将失效。计算缓存校验和时不考虑文件的修改时间(mtime),如果只有复制的文件的 mtime发生了更改,则缓存不会失效。
  • 除了ADD和COPY命令之外,缓存检查不会查看容器中的文件来确定缓存匹配。例如,在处理命令时,RUN apt-get -y update不会检查容器中更新的文件来确定是否存在缓存命中。在这种情况下,只使用命令字符串本身来查找匹配项。


一旦缓存失效,所有后续的 Dockerfile 命令都会生成新的图像,并且不会使用缓存。


如果构建的镜像包含多个层,并且想要确保构建缓存可重复使用,请尽可能按从更改频率较低的顺序排列指令。


2、RUN 指令


指令缓存RUN不会在构建之间自动失效。假设您的 Dockerfile 中有一步要安装curl:


FROM alpine:3.20 AS install
RUN apk add curl


这并不意味着curl在镜像中的版本始终是最新的,一周后重建镜像仍将获得与之前相同的软件包,如果要强制重新执行该RUN指令,可以:

  • 确保之前的一个层已经改变;
  • 使用以下方法在构建之前清除构建缓存 docker builder prune;
  • 使用--no-cache或--no-cache-filter选项;


该--no-cache-filter选项允许您指定特定的构建阶段以使缓存无效:


$ docker build --no-cache-filter install .


如果要使RUN指令的缓存失效,可以传递一个构建参数,该参数带有变化的值,构建参数确实会导致缓存失效,因为RUN指令是使用命令字符串本身来查找匹配缓存的。


七、优化总结


要对镜像进行优化和精简,你可以采取以下步骤:


1、使用多阶段构建:使用多阶段构建可以减少镜像的大小,因为你可以在不同的镜像中执行不同的构建步骤,并在最终镜像中只保留必要的文件和依赖。

2、清理不需要的文件和依赖:在Dockerfile中,你可以使用一系列命令来清理不需要的文件和依赖,例如使用rm命令删除不需要的文件,使用--no-cache选项来清理缓存等。

3、使用轻量的基础镜像:选择一个轻量的基础镜像作为你的镜像的基础,这样可以减少镜像的大小。

4、合并镜像层:在Dockerfile中,你可以使用多个命令来合并多个操作,这样可以减少镜像的层数和大小。

5、我们应该把变化最少的部分放在 Dockerfile 的前面,将经常变化的内容放在最后面,这样可以充分利用镜像缓存。


通过以上步骤,你可以对镜像进行优化和精简,减少其大小并提高性能。


Dockerfile 编码规约:


规约项

Level

说明

Dockerfile指令不应超过20条

WARN

层数过多

不应该超过3条连续RUN命令

WARN

层数过多


CMD/ENTRYPOINT/EXPOSE/LABEL指令位置应在COPY/RUN之前

INFO

动静分离原则

RUN 指令应在COPY主包指令之前

ERROR

动静分离原则

RUN yum指令后应以yum clean all收尾

WARN

最小原则

RUN pip install应该加--no-cache-dir参数

ERROR

最小原则

RUN npm install指令应加--no-cache参数

ERROR

最小原则

单层镜像最大的编译时间不应超过80秒

WARN

构建效率过低

单层镜像体积不应超过500M

WARN

最小原则

构建时发生变化的层不应该超过3层

INFO

动静分离

base镜像体积不应超过2G

WARN

最小原则


最后在网上找到一些其他的优化手段,在这里汇总一下:

  • 编写.dockerignore 文件
  • 容器只运行单个应用
  • 将多个 RUN 指令合并为一个
  • 基础镜像的标签不要用 latest
  • 每个 RUN 指令后删除多余文件
  • 选择合适的基础镜像(alpine 版本最好)
  • 设置 WORKDIR 和 CMD
  • 使用 ENTRYPOINT (可选)
  • 在 entrypoint 脚本中使用 exec
  • COPY 与 ADD 优先使用前者
  • 合理调整 COPY 与 RUN 的顺序
  • 设置默认的环境变量,映射端口和数据卷
  • 使用 LABEL 设置镜像元数据
  • 添加 HEALTHCHECK


>>>>

参考资料


  • Building best practices:https://docs.docker.com/build/building/best-practices/


作者丨惜鸟

来源丨公众号:阿里云开发者(ID:ali_tech)

dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn

相关推荐

安全教育登录入口平台(安全教育登录入口平台官网)

122交通安全教育怎么登录:122交通网的注册方法是首先登录网址http://www.122.cn/,接着打开网页后,点击右上角的“个人登录”;其次进入邮箱注册,然后进入到注册页面,输入相关信息即可完...

大鱼吃小鱼经典版(大鱼吃小鱼经典版(经典版)官方版)

大鱼吃小鱼小鱼吃虾是于谦跟郭麒麟的《我的棒儿呢?》郭德纲说于思洋郭麒麟作诗的相声,最后郭麒麟做了一首,师傅躺在师母身上大鱼吃小鱼小鱼吃虾虾吃水水落石出师傅压师娘师娘压床床压地地动山摇。...

谷歌地球下载高清卫星地图(谷歌地球地图下载器)
  • 谷歌地球下载高清卫星地图(谷歌地球地图下载器)
  • 谷歌地球下载高清卫星地图(谷歌地球地图下载器)
  • 谷歌地球下载高清卫星地图(谷歌地球地图下载器)
  • 谷歌地球下载高清卫星地图(谷歌地球地图下载器)
哪个软件可以免费pdf转ppt(免费的pdf转ppt软件哪个好)
哪个软件可以免费pdf转ppt(免费的pdf转ppt软件哪个好)

要想将ppt免费转换为pdf的话,我们建议大家可以下一个那个wps,如果你是会员的话,可以注册为会员,这样的话,在wps里面的话,就可以免费将ppt呢转换为pdfpdf之后呢,我们就可以直接使用,不需要去直接不需要去另外保存,为什么格式转...

2026-02-04 09:03 off999

电信宽带测速官网入口(电信宽带测速官网入口app)

这个网站看看http://www.swok.cn/pcindex.jsp1.登录中国电信网上营业厅,宽带光纤,贴心服务,宽带测速2.下载第三方软件,如360等。进行在线测速进行宽带测速时,尽...

植物大战僵尸95版手机下载(植物大战僵尸95 版下载)

1可以在应用商店或者游戏平台上下载植物大战僵尸95版手机游戏。2下载教程:打开应用商店或者游戏平台,搜索“植物大战僵尸95版”,找到游戏后点击下载按钮,等待下载完成即可安装并开始游戏。3注意:确...

免费下载ppt成品的网站(ppt成品免费下载的网站有哪些)

1、Chuangkit(chuangkit.com)直达地址:chuangkit.com2、Woodo幻灯片(woodo.cn)直达链接:woodo.cn3、OfficePlus(officeplu...

2025世界杯赛程表(2025世界杯在哪个国家)

2022年卡塔尔世界杯赛程公布,全部比赛在卡塔尔境内8座球场举行,2022年,决赛阶段球队全部确定。揭幕战于当地时间11月20日19时进行,由东道主卡塔尔对阵厄瓜多尔,决赛于当地时间12月18日...

下载搜狐视频电视剧(搜狐电视剧下载安装)

搜狐视频APP下载好的视频想要导出到手机相册里方法如下1、打开手机搜狐视频软件,进入搜狐视频后我们点击右上角的“查找”,找到自已喜欢的视频。2、在“浏览器页面搜索”窗口中,输入要下载的视频的名称,然后...

pubg免费下载入口(pubg下载入口官方正版)
  • pubg免费下载入口(pubg下载入口官方正版)
  • pubg免费下载入口(pubg下载入口官方正版)
  • pubg免费下载入口(pubg下载入口官方正版)
  • pubg免费下载入口(pubg下载入口官方正版)
永久免费听歌网站(丫丫音乐网)

可以到《我爱音乐网》《好听音乐网》《一听音乐网》《YYMP3音乐网》还可以到《九天音乐网》永久免费听歌软件有酷狗音乐和天猫精灵,以前要跳舞经常要下载舞曲,我从QQ上找不到舞曲下载就从酷狗音乐上找,大多...

音乐格式转换mp3软件(音乐格式转换器免费版)

有两种方法:方法一在手机上操作:1、进入手机中的文件管理。2、在其中选择“音乐”,将显示出手机中的全部音乐。3、点击“全选”,选中所有音乐文件。4、点击屏幕右下方的省略号图标,在弹出菜单中选择“...

电子书txt下载(免费的最全的小说阅读器)

1.Z-library里面收录了近千万本电子书籍,需求量大。2.苦瓜书盘没有广告,不需要账号注册,使用起来非常简单,直接搜索预览下载即可。3.鸠摩搜书整体风格简洁清晰,书籍资源丰富。4.亚马逊图书书籍...

最好免费观看高清电影(播放免费的最好看的电影)

在目前的网上选择中,IMDb(互联网电影数据库)被认为是最全的电影网站之一。这个网站提供了各种类型的电影和电视节目的海量信息,包括剧情介绍、演员表、评价、评论等。其还提供了有关电影制作背后的详细信息,...

孤单枪手2简体中文版(孤单枪手2简体中文版官方下载)

要将《孤胆枪手2》游戏的征兵秘籍切换为中文,您可以按照以下步骤进行操作:首先,打开游戏设置选项,通常可以在游戏主菜单或游戏内部找到。然后,寻找语言选项或界面选项,点击进入。在语言选项中,选择中文作为游...

取消回复欢迎 发表评论: