docker多阶段构建镜像

       工作中常常用到docker,现在有这样一个场景:已经有一个打好的docker镜像A,主要是包含系统文件(1-3G)、pyhton env(9-10G)文件、模型权重文件modelA(65G)和python代码文件。同时重新安装pyhton env耗时很久(安装torch/cuda/sglang)等等。现在要把modelA切换为modelB(也是65G),要快速的构建好docker image B,同时又要保证docker image B的体积尽可能的小。那么这个dockerfile该怎么写呢?

        为了构建的时间最小,因此python env 不要再次安装(这个一般需要2-3个小时,也假设之前构建docker镜像A的时候 pip 没有缓存),那么就得依赖docker镜像A;为了最终构建镜像体积小,所以要不镜像A中的模型权重文件modelA给删除掉。按照这个思路貌似就很容易完成这个任务。

FROM imageA
RUN rm -rf /app/*.py
RUN rm -rf /app/modelACOPY models/modelB modelB 
ENV PATH="/app:$PATH"
COPY config.toml .
COPY *.py .
RUN python3 -m pip install pytomlpp -i https://pypi.tuna.tsinghua.edu.cn/simple
CMD ["python", "llm_sglang_server_ws.py"]

最后运行docker build -t  imageB -f ./Dockerfile . 构建新的镜像,最后发现imageB的体积比imageA要大65G,貌似RUN rm -rf /app/modelA 并没有生效一样。这是因为docker镜像的存储是按照layer来进行的,dockerfile中每一条命令FROM、COPY、RUN、CMD等都会产生一个layer,每一层layer都是基于之前的所有layer来进行构建的。docker镜像的大小就是所有layer的大小之和。具体都上面的dockerfile中,RUN rm -rf /app/modelA 这个命令指示标记删除modelA在最后的镜像中不可见,但是modelA仍然存在某些layer中

FROM imageA                                                                                                          75G
RUN rm -rf /app/*.py                                                                                                 0B
RUN rm -rf /app/modelA                                                                                           0B

COPY models/modelB modelB                                                                                 65G
ENV PATH="/app:$PATH"                                                                                        0B
COPY config.toml .                                                                                                   1kB
COPY *.py .                                                                                                               80kB
RUN python3 -m pip install pytomlpp -i https://pypi.tuna.tsinghua.edu.cn/simple     13MB
CMD ["python", "llm_sglang_server_ws.py"]                                                              0B

因此总计 65G+75G = 140G

因此我们就需要采用多阶段来构建,多阶段就是使用多个FROM命令,有个特点就是镜像只会保留最后一个FROM后面的非FROM命令的层。先把dockerfile多阶段构建的给出来

FROM imageA as builder
RUN rm -rf /app/*.py
RUN rm -rf /app/modelAFROM scratch
WORKDIR /app
COPY --from=builder / /
COPY models/modelB modelBARG docker_dir="docker"
ENV PATH="/app:$PATH"
COPY config.toml .
COPY *.py .
RUN python3 -m pip install pytomlpp -i https://pypi.tuna.tsinghua.edu.cn/simple
CMD ["python", "llm_sglang_server_ws.py"]

分析一下这个dockerfile以及构建后的镜像

首先FROM scratch引入了一个空镜像,不占空间;COPY --from=builder / / 从第一阶段的镜像中把/路径下的文件全部复制过来了(包含各种系统文件、python env等),docker history Image 看看构建后的镜像:

镜像总计9层,每层的大小也具体显示出来了,符合我们上述的分析——只有最后一个FROM后的命令对应的layer保留下来了。

以上内容仅仅是对当前场景怎么快速构建一个体积相对较小同时有满足需求的镜像,给出了演示和分析。关于docker镜像的压缩和精简,在构建的时候还有其他的一些技巧,合并多个同类命令为一个命令、清除缓存、使用轻量化的基础镜像等,这里我们就不做过多的学习了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/81921.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

目标检测 RT-DETR(2023)详细解读

文章目录 主干网络:Encoder:不确定性最小Query选择Decoder网络: 将DETR扩展到实时场景,提高了模型的检测速度。网络架构分为三部分组成:主干网络、混合编码器、带有辅助预测头的变换器编码器。具体来说,先利…

学习 Pinia 状态管理【Plan - May - Week 2】

一、定义 Store Store 由 defineStore() 定义,它的第一个参数要求独一无二的id import { defineStore } from piniaexport const useAlertsStore defineStore(alert, {// 配置 })最好使用以 use 开头且以 Store 结尾 (比如 useUserStore,useCartStore&a…

智能制造:基于AI制造企业解决方案架构设计【附全文阅读】

该方案面向制造企业管理者、技术工程师及智能制造转型需求企业,聚焦AI技术在制造业的落地应用。核心内容以AI开放平台为基础,构建“感知层-算法层-平台层-认知层”技术架构,提供从数据采集、模型训练到智能检测的全流程解决方案。 方案通过机…

JVM 高质量面试题

📌 文章目录 一、JVM 内存结构与运行时模型1. JVM 内存结构分区及作用2. 栈帧结构及方法调用链维护3. 逃逸分析及其对对象分配策略的影响4. TLAB 的作用及提升对象创建效率的机制二、垃圾回收器与 GC 调优1. CMS 与 G1 垃圾收集器的设计区别及适用场景2. Full GC 频繁问题的排…

使用Spring Boot和Spring Security构建安全的RESTful API

使用Spring Boot和Spring Security构建安全的RESTful API 引言 在现代Web开发中,安全性是一个不可忽视的重要方面。Spring Boot和Spring Security是Java生态中广泛使用的框架,它们提供了强大的工具来保护RESTful API。本文将介绍如何结合这两个框架&am…

Web项目流程总结

前端 1.下载pnpm管理器 pnpm是一种JavaScript包管理器。 前提:确保安装了Node.js 和 npm 打开cmd,以管理员身份运行(输入以下指令) npm install -g pnpm 安装成功后显示: npm: 这是 Node.js 的包管理工具&#xf…

Java中static关键字深度解析:从入门到高阶实战

Java中static关键字深度解析:从入门到高阶实战 目录 static的本质与核心特性静态变量 vs 实例变量:底层对比静态方法的设计哲学与应用场景高级用法:突破常规的static技巧 4.1 静态代码块:类加载的“初始化引擎”4.2 静态内部类&…

学习人工智能:从0到1的破局指南与职业成长路径

当AI绘画工具在几秒内生成一幅媲美专业画师的作品,当AI程序员自主优化代码逻辑,当AI客服精准解答复杂问题——一个现实愈发清晰:人工智能(AI)不再是科技公司的专属游戏,而是每个普通人必须直面的时代命题。…

2025年医美行业报告60+份汇总解读 | 附 PDF 下载

原文链接:https://tecdat.cn/?p42122 医美行业在消费升级与技术迭代的双重驱动下,已从边缘市场逐步走向主流。数据显示,2024 年中国医美市场规模突破 3000 亿元,年复合增长率达 15%,但行业仍面临正品率不足、区域发展…

深入了解Springboot框架的启动流程

目录 1、介绍 2、执行流程 1、运行run方法 2、初始化SpringApplication对象 1、确定容器类型 3、加载所有的初始化器 4、加载Spring上下文监听器 5、设置程序运行的主类 3、进入run方法 1、开启计时器 2、Headless模式配置 3、获取并启用监听器 4、准备环境 1、设…

【Java多态】:灵活编程的核心

🎁个人主页:User_芊芊君子 🎉欢迎大家点赞👍评论📝收藏⭐文章 🔍系列专栏:【Java】内容概括 【前言】 在Java面向对象编程的世界中,多(Polymorphism) 是一个核…

Python打卡训练营day33——2025.05.22

知识点回顾: PyTorch和cuda的安装 查看显卡信息的命令行命令(cmd中使用) cuda的检查 简单神经网络的流程 数据预处理(归一化、转换成张量) 模型的定义 继承nn.Module类 定义每一个层 定义前向传播流程 定义损失函数和优…

uni-app学习笔记九-vue3 v-for指令

v-for 指令基于一个数组来渲染一个列表。v-for 指令的值需要使用 item in items 形式的特殊语法&#xff0c;其中 items 是源数据的数组&#xff0c;而 item 是迭代项的别名&#xff1a; <template><view v-for"(item,index) in 10" :key"index"…

【C++算法】70.队列+宽搜_N 叉树的层序遍历

文章目录 题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a; 题目链接&#xff1a; 429. N 叉树的层序遍历 题目描述&#xff1a; 解法 使用队列层序遍历就可以了。 先入根节点1。queue&#xff1a;1 然后出根节点1&#xff0c;入孩子节点2&#xff0c;3&a…

pycharm无法正常调试问题

pycharm无法正常调试问题 1.错误代码 已连接到 pydev 调试器(内部版本号 231.8109.197)Traceback (most recent call last):File "E:\Python\pycharm\PyCharm 2023.1\plugins\python\helpers\pydev\_pydevd_bundle\pydevd_comm.py", line 304, in _on_runr r.deco…

【机器学习基础】机器学习入门核心算法:线性回归(Linear Regression)

机器学习入门核心算法&#xff1a;线性回归&#xff08;Linear Regression&#xff09; 1. 算法逻辑2. 算法原理与数学推导3. 评估指标4. 应用案例5. 面试题6. 扩展分析总结 1. 算法逻辑 核心思想 通过线性方程拟合数据&#xff0c;最小化预测值与真实值的误差平方和&#xff0…

手机打电话时由对方DTMF响应切换多级IVR语音菜单(话术脚本与实战)

手机打电话时由对方DTMF响应切换多级IVR语音菜单 &#xff08;话术脚本与实战&#xff09; --本地AI电话机器人 上一篇&#xff1a;手机打电话时由对方DTMF响应切换多级IVR语音应答&#xff08;二&#xff09; 下一篇&#xff1a;手机打电话时由对方DTMF响应切换多级IVR语音…

flutter dart class语法说明、示例

&#x1f539; Dart 中的 class 基本语法 class ClassName {// 属性&#xff08;字段&#xff09;数据类型 属性名;// 构造函数ClassName(this.属性名);// 方法返回类型 方法名() {// 方法体} }✅ 示例&#xff1a;创建一个简单的 Person 类 class Person {// 属性String name;…

Apollo10.0学习——planning模块(10)之依赖注入器injector_

好不好奇injector_是干什么用的&#xff1f;为什么planning每个模块都要初始化这个变量&#xff1f; 类功能概述 DependencyInjector&#xff08;依赖注入器&#xff09;是一个 集中管理规划模块关键数据和服务 的容器类。它通过提供统一的访问接口&#xff0c;解耦各个组件之…

关于vue彻底删除node_modules文件夹

Vue彻底删除node_modules的命令 vue的node_modules文件夹非常大,常规手段根本无法删除. 解决方法: 在node_modules文件夹所在的路径运行命令窗口,并执行下面的命令. npm install rimraf -g rimraf node_modules说明&#xff1a; npm install rimraf -g 该命令是安装 node…