1.在 Nvidia Docker 容器编译构建显存优化加速组件 xFormers
2.Docker 安装及镜像管理
3.Docker 源码分析
4.DockerMySQL 源码构建 Docker 镜像(基于 ARM 64 架构)
5.深入 Dify 源码,编译编译洞察 Dify RAG 核心机制
6.纯干货!源码源码构建Dockfile镜像的编译编译十三个最佳实践点
在 Nvidia Docker 容器编译构建显存优化加速组件 xFormers
本篇文章,聊聊如何在新版本 PyTorch 和 CUDA 容器环境中完成 xFormers 的源码源码编译构建。
让你的编译编译模型应用能够跑的更快。
写在前面
xFormers[1] 是源码源码面相算命程序源码 FaceBook Research (Meta)开源的使用率非常高的 Transformers 加速选型,当我们使用大模型的编译编译时候,如果启用 xFormers 组件,源码源码能够获得非常明显的编译编译性能提升。
因为 xFormers 对于 Pytorch 和 CUDA 新版本支持一般会晚很久。源码源码所以,编译编译时不时的源码源码我们能够看到社区提出不能在新版本 CUDA 中构建的问题( #[2]或 #[3]),以及各种各样的编译编译编译失败的问题。
另外,源码源码xFormers 的编译编译安装还有一个问题,会在安装的时候调整当前环境已经安装好的 PyTorch 和 Numpy 版本,比如我们使用的是已经被验证过的环境,比如 Nvidia 的月度发布的容器环境,这显然是我们不乐见的事情。
下面,我们就来解决这两个问题,让 xFormers 能够在新的 CUDA 环境中完成编译,以及让 xFormers 的安装不需要变动我们已经安装好的 Pytorch 或者 Numpy。
环境准备
环境的准备一共有两步,下载容器和 xFormers 源代码。
Nvidia 容器环境
在之前的 许多文章[4]中,我提过很多次为了高效运行模型,我推荐使用 Nvidia 官方的容器镜像( nvcr.io/nvidia/pytorch:.-py3[5])。
下载镜像很简单,一条命令就行:
完成镜像下载后,准备工作就完成了一半。
准备好镜像后,我们可以检查下镜像中的具体组件环境,使用docker run 启动镜像:
然后,使用python -m torch.utils.collect_env 来获取当前环境的信息,方便后续完成安装后确认原始环境稳定:
获取 xFormers
下载 xFormers 的源代码,并且记得使用--recursive 确保所有依赖都下载完毕:
xFormers 的源码包含三个核心组件cutlass、flash-attention、sputnik,android 软件 源码除去最后一个开源软件在 xFormers 项目 sputnik 因为 Google 不再更新,被固定了代码版本,其他两个组件的版本分别为:cutlass@3.2 和 flash-attention@2.3.6。
Dao-AILab/flash-attention[6]目前最新的版本是 v2.4.2,不过更新的主干版本包含了更多错误的修复,推荐直接升级到最新版本。在 v2.4.2 版本中,它依赖的 cutlass 版本为 3.3.0,所以我们需要升级 cutlass 到合适的版本。
Nvidia/cutlass[7] 在 3.1+ 的版本对性能提升明显。
不过如果直接更新 3.2 到目前最新的 3.4flash-attention 找不到合适的版本,会发生编译不通过的问题,所以我们将版本切换到 v3.3.0 即可。
另外,在前文中提到了在安装 xFormers 的时候,会连带更新本地已经安装好的依赖。想要保护本地已经安装好的环境不被覆盖,尤其是 Nvidia 容器中的依赖不被影响,我们需要将xformers/requirements.txt 内容清空。
好了,到这里准备工作就结束了。
完成容器中的 xFormers 的安装
想要顺利完成 xFormers 的构建,还有一些小细节需要注意。为了让我们能够从源码进行构建,我们需要关闭我们下载 xFormers 路径的 Git 安全路径检查:
为了让构建速度有所提升,我们需要安装一个能够让我们加速完成构建的工具ninja:
当上面的工具都完成后,我们就可以执行命令,开始构建安装了:
需要注意的是,默认情况下安装程序会根据你的 CPU 核心数来设置构建进程数,不过过高的工作进程,会消耗非常多的内存。如果你的 CPU 核心数非常多,那么默认情况下直接执行上面的命令,会得到非常多的Killed 的编译错误。
想要解决这个问题,我们需要设置合理的MAX_JOBS 参数。如果你的硬件资源有限,可以设置 MAX_JOBS=1,79小说源码如果你资源较多,可以适当增加数值。我的构建设备有 G 内存,我一般会选择设置 MAX_JOBS=3 来使用大概最多 GB 的内存,来完成构建过程,MAX_JOBS 的构建内存消耗并不是完全严格按照线性增加的,当我们设置为 1 的时候,GB 的设备就能够完成构建、当我们设置为 2 的时候,使用 GB 的设备构建会比较稳妥,当设置到 4 的时候,构建需要的内存就需要 GB 以上了。
构建的过程非常漫长,过程中我们可以去干点别的事情。
当然,为了我们后续使用镜像方便,最好的方案是编写一个 Dockerfile,然后将构建的产物保存在镜像中,以方便后续各种场景使用:
在构建的时候,我们可以使用类似下面的命令,来搞定既使用了最新的 Nvidia 镜像,包含最新的 Pytorch 和 CUDA 版本,又包含 xFormers 加速组件的容器环境。
如果你是在本机上进行构建,没有使用 Docker,那么构建成功,你将看到类似下面的日志:
等待漫长的构建结束,我们可以使用下面的命令,来启动一个包含构建产物的容器,来测试下构建是否成功:
当我们进入容器的交互式命令行之后,我们可以执行python -m xformers.info,来验证 xFromers 是否构建正常:
以及,使用python -m torch.utils.collect_env 再次确认下环境是否一致:
最后
好了,这篇文章就先写到这里啦。
Docker 安装及镜像管理
Docker 安装及镜像管理
安装Docker首先需要下载docker源,通常我们会选择修改源地址以从清华源加速下载,以提高下载速度,比如使用阿里云镜像加速。recovery源码更新Docker由docker client和docker server组成,可以通过命令行工具如`docker version`和`docker info`查看系统信息。 初体验Docker,如安装Nginx,通常会从官网下载源码,进行编译安装,并配置启动。为解决镜像拉取速度慢的问题,可以登录阿里云或Docker中国官方镜像加速服务获取独立分配的加速地址。镜像管理
在管理镜像时,搜索镜像时应关注名称、描述、受欢迎程度、官方提供状态。官方镜像如CentOS是首选,stars数量多的也值得考虑,官方镜像仓库地址为hub.docker.com。 执行操作如拉取镜像,可以使用`docker pull`,例如官方的`docker pull centos:6.9`或私有仓库的`docker pull ..1.:/busybox`。查看镜像列表使用`docker images`或`docker image ls`,删除镜像则用`docker rmi`命令,例如`docker image rm alpine`。 镜像导出和导入也很重要,导出镜像使用`docker image save -o 导出路径 导出镜像名字`,导入则通过`docker image load`并指定导入路径。Docker 源码分析
本文旨在解析Docker的核心架构设计思路,内容基于阅读《Docker源码分析》系文章后,整理的核心架构设计与关键部分摘抄。Docker是Docker公司开源的基于轻量级虚拟化技术的容器引擎项目,使用Go语言开发,遵循Apache 2.0协议。Docker提供快速自动化部署应用的能力,利用内核虚拟化技术(namespaces及cgroups)实现资源隔离与安全保障。相比虚拟机,Docker容器运行时无需额外的系统开销,提升资源利用率与性能。Docker迅速获得业界认可,爱问源码包括Google、Microsoft、VMware在内的领导者支持。Google推出Kubernetes提供Docker容器调度服务,Microsoft宣布Azure支持Kubernetes,VMware与Docker合作。Docker在分布式应用领域获得万美元的C轮融资。
Docker的架构主要由Docker Client、Docker Daemon、Docker Registry、Graph、Driver、libcontainer以及Docker container组成。
Docker Client:用户通过命令行工具与Docker Daemon建立通信,发起容器管理请求。
Docker Daemon:后台运行的系统进程,接收并处理Docker Client请求,通过路由与分发调度执行相应任务。
Docker Registry:存储容器镜像的仓库,支持公有与私有注册。
Graph:存储已下载镜像,并记录镜像间关系的数据库。
Driver:驱动模块,实现定制容器执行环境,包括graphdriver、networkdriver和execdriver。
libcontainer:库,使用Go语言设计,直接访问内核API,提供容器管理功能。
Docker container:Docker架构的最终服务交付形式。
架构内各模块功能如下:
Docker Client:用户与Docker Daemon通信的客户端。
Docker Daemon:后台服务,接收并处理请求,执行job。
Graph:存储容器镜像,记录镜像间关系。
Driver:实现定制容器环境,包括管理、网络与执行驱动。
libcontainer:库,提供内核访问,实现容器管理。
Docker container:执行容器,提供隔离环境。
核心功能包括从Docker Registry下载镜像、创建容器、运行命令与网络配置。
总结,通过Docker源码学习,深入了解其设计、功能与价值,有助于在分布式系统实现中找到与已有平台的契合点。同时,熟悉Docker架构与设计思想,为云计算PaaS领域带来实践与创新启发。
DockerMySQL 源码构建 Docker 镜像(基于 ARM 架构)
基于 ARM 架构,为避免MySQL版本变化带来的额外成本,本文将指导你如何从头构建MySQL 5.7.的Docker镜像。首先,我们从官方镜像的Dockerfile入手,但官方仅提供MySQL 8.0以上版本的ARM镜像,因此需要采取特殊步骤。 步骤一,使用dfimage获取MySQL 5.7.的原始Dockerfile,注意其原文件中通过yum安装的逻辑不适用于ARM,因为官方yum源缺少该版本的ARM rpm。所以,你需要:在ARM环境中安装必要的依赖
下载源码并安装
修改源码配置以适应ARM架构
编译源码生成rpm文件,结果存放在/root/rpmbuild/RPMS/aarch目录
构建镜像的Dockerfile、docker-entrypoint.sh脚本(解决Kylin V兼容性问题,会在后续文章详细说明)以及my.cnf文件是构建过程中的关键组件。虽然原Dockerfile需要调整以消除EOF块的报错,但整个过程需要细心处理和定制化以适应ARM平台。深入 Dify 源码,洞察 Dify RAG 核心机制
深入探究Dify源码,揭示RAG核心机制的关键环节 在对Dify的完整流程有了初步了解后,发现其RAG检索效果在实际部署中不尽如人意。因此,针对私有化部署的Dify,我结合前端配置和实现流程,详细解析了技术细节,旨在帮助调整知识库配置或进行定制化开发。Docker私有化部署技术方案
本文重点聚焦于Dify docker私有化部署的默认技术方案,特别是使用Dify和Xinference的GPU环境部署。若想了解更多,可查阅Dify与Xinference的集成部署教程。RAG核心流程详解
Extractor:负责原始文件内容的提取,主要在api/core/rag/extractor/extract_processor.py中实现。分为Dify默认解析和Unstructured解析,后者可能涉及付费,通常Dify解析更为常用。
Cleaner:清洗解析内容,减少后续处理负担,主要基于规则进行过滤,用户可在前端进行调整。
Splitter:文件分片策略,Dify提供自动和自定义两种,影响检索效果。
Retrieval:Dify支持多种检索模式,包括关键词检索和向量数据库检索,向量库的选择对效果有很大影响。
Rerank:对检索结果进行排序,配置Top K和score阈值,但存在设计上的不足。
总结与优化建议
Dify的RAG服务提供了基础框架,但性能优化空间大。通过调整配置,特别是针对特定业务场景,可以改善检索效果。对RAG效果要求高的用户,可能需要进行定制化的二次开发和优化。纯干货!构建Dockfile镜像的十三个最佳实践点
编写.dockerignore文件
在构建镜像时,Docker需要准备上下文,将所有需要的文件收集到进程中。默认上下文包含Dockerfile目录中的所有文件,但实际上并不需要.git目录、.vscode目录、.idea目录等内容。.dockerignore文件的用法与.gitignore类似,可以忽略一些不需要的文件,有效加快构建时间并减少Docker镜像大小。
样例:
一个容器只运行单个应用
从技术角度讲,可以在Docker容器中运行多个进程,但这样做会让你非常痛苦。因此,建议为每个应用构建单独的Docker镜像。
选择合适的基础镜像
合适的基础镜像如scratch、busybox、alpine、distroless等,有助于减少镜像大小。较小的镜像表示无用程序更少,提高了安全性。
将多个RUN指令合并为一个
Docker镜像是分层的,重要知识点包括:现在,将所有RUN指令合并为一个。同时删除apt-get upgrade,因为它会使镜像构建非常不确定。记住,只能将变化频率相同的指令合并在一起,如将node.js安装与npm模块安装放在一起。
基础镜像和生产镜像的标签不要使用latest
当镜像没有指定标签时,默认使用latest。这可能导致镜像更新时构建失败。若确实需要最新版基础镜像,使用latest标签;否则,最好指定明确的镜像标签。
样例:
每个RUN指令后删除多余文件
更新apt-get源后,下载、解压并安装软件包,这些文件在运行应用时不需要保存在Docker镜像中。删除它们可以减少镜像大小。
样例:
在Dockerfile中删除/var/lib/apt/lists/目录中的文件(由apt-get update生成)。
设置WORKDIR和CMD
WORKDIR指令可以设置默认目录,即运行RUN、CMD、ENTRYPOINT指令的地方。CMD指令设置容器创建时执行的默认命令,应将命令写入数组中。
样例:
使用ENTRYPOINT时,用exec启动命令(可选)
在使用entrypoint的脚本中,要使用exec命令运行应用。不使用exec,容器关闭时SIGTERM信号会被bash脚本进程吞没。exec命令启动的进程可以取代脚本进程,确保所有信号正常工作。
相比ADD,优先使用COPY
COPY指令用于简单文件拷贝,ADD指令则可以下载远程文件和解压压缩包,相对复杂。
样例:
设置默认的环境变量,映射端口和数据卷
运行Docker容器时可能需要环境变量。在Dockerfile中设置默认环境变量。同时,应在Dockerfile中设置映射端口和数据卷。
样例:
ENV指令指定的环境变量在容器中可用。构建镜像时需要指定的变量,使用ARG指令。
使用LABEL设置镜像元数据
使用LABEL指令为镜像设置元数据,例如创建者或描述。弃用了MAINTAINER指令,外部程序如nvidia-docker可能需要com.nvidia.volumes.needed等元数据。
样例:
一个镜像可以有多个label。尽可能将多个label合并到一个LABEL指令中,避免构建出低效镜像。
添加HEALTHCHECK
运行容器时,使用--restart always选项,当容器崩溃时Docker守护进程会重启容器。HEALTHCHECK指令可以周期性检查容器健康状况,指定命令返回0表示正常,返回1表示异常。
样例:
当请求失败时,curl --fail命令返回非0状态。
合理调整COPY和RUN的顺序
应将变化最少的部分放在Dockerfile的前面,充分利用镜像缓存。
样例:
源代码经常变化,每次构建镜像时都需要重新安装NPM模块。因此,先拷贝package.json,然后安装NPM模块,最后拷贝其余源代码。这样即使源代码变化,也不需要重新安装NPM模块。
参考文档
Docker源码安装附内网镜像安装演示
系统版本要求源码包下载
官网下载地址(download.docker.com/lin...)
我这里已docker-...tgz该版本做演示
1.下载源码包文件到本地
2.通过远程连接工具(xShell、SecureCRT等将源码包文件上载到服务器自定义目录)
3.解压文件
4.配置docker为service服务
5.添加可执行权限
注:如遇到启动不成功可通过状态查询、/var/log/messages/运行日志或直接使用dockerd命令查看错误信息,如还解决不了建议服务器重启一下在运行docker启动命令
6.配置镜像加速
7.检查安装版本内网下载镜像
注:使用docker pull拉取镜像的时候需要网络,但是项目部署一般都是在内网。内网访问不了外网,所以需要在外网环境下把需要的镜像拉取下来打包,然后拷贝到内网,载入到内网的docker
1.在外网机器上拉取mysql镜像,可以看到外网的docker已经拉取了镜像。
2.将镜像打包成tar压缩包
3.将打包好的mysql镜像包通过远程工具下载到本地
4.拷贝到内网linux服务器并载入docker
docker基础命令使用(扩展)下载镜像:(hub.docker.com/search/官网镜像地址)
docker pull [IMAGE_NAME]:[TAG] #命令格式
docker pull mysql:8.0 #下载mysql8.0镜像(不指定默认下载最新版本)
查看当前镜像版本
docker -v #查看当前安装版本
docker version #查看版本信息
docker info #查看系统信息
docker images #查看当前镜像
docker search 镜像名 #搜索镜像
镜像、容器删除
docker rm 容器ID
docker rm 容器名字
docker rmi 镜像ID
docker rmi 镜像名
docker rmi -f 镜像ID #强制删除
创建网络及数据卷
docker volume create +数据卷名称
docker volume list #查看当前数据卷信息
docker network create -d bridge +网络名称
docker network ls #查看当前网络
docker inspect containername +id #查看容器的hash值
启动、关闭容器
docker stop $(docker ps -a | awk '{ print $1}' | tail -n +2) #关闭所有容器
docker start $(docker ps -a | awk '{ print $1}' | tail -n +2) #开启所有容器
杂
docker inspect 容器ID (使用该命令重点关注容器ip) #查看容器/镜像元数据
docker exec #在运行的容器中执行命令
docker exec -it 容器ID /bin/bash #以交互模式开启伪终端