1.在 Nvidia Docker 容器编译构建显存优化加速组件 xFormers
2.DockerMySQL 源码构建 Docker 镜像(基于 ARM 64 架构)
3.Docker 这九个不同的源码应用场景,你都用到了吗?
4.简简单单将Java应用封装成Docker镜像
5.为Python应用选择最好的编译Docker镜像
6.Docker 安装及镜像管理
在 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 的vs2005源码源代码,并且记得使用--recursive 确保所有依赖都下载完毕:
xFormers 的源码包含三个核心组件cutlass、flash-attention、sputnik,除去最后一个开源软件在 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,如果你资源较多,可以适当增加数值。我的构建设备有 G 内存,我一般会选择设置 MAX_JOBS=3 来使用大概最多 GB 的内存,来完成构建过程,MAX_JOBS 的构建内存消耗并不是完全严格按照线性增加的,当我们设置为 1 的时候,GB 的设备就能够完成构建、当我们设置为 2 的时候,使用 GB 的设备构建会比较稳妥,当设置到 4 的时候,构建需要的内存就需要 GB 以上了。
构建的过程非常漫长,过程中我们可以去干点别的事情。
当然,为了我们后续使用镜像方便,最好的方案是编写一个 Dockerfile,然后将构建的产物保存在镜像中,以方便后续各种场景使用:
在构建的时候,我们可以使用类似下面的命令,来搞定既使用了最新的 Nvidia 镜像,包含最新的 Pytorch 和 CUDA 版本,又包含 xFormers 加速组件的容器环境。
如果你是在本机上进行构建,没有使用 Docker,那么构建成功,你将看到类似下面的java导入源码包日志:
等待漫长的构建结束,我们可以使用下面的命令,来启动一个包含构建产物的容器,来测试下构建是否成功:
当我们进入容器的交互式命令行之后,我们可以执行python -m xformers.info,来验证 xFromers 是否构建正常:
以及,使用python -m torch.utils.collect_env 再次确认下环境是否一致:
最后
好了,这篇文章就先写到这里啦。
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平台。Docker 这九个不同的应用场景,你都用到了吗?
Docker 是一个开源的容器引擎,能够为任何应用创建轻量级、可移植、自给自足的容器。开发者与系统管理员可以在笔记本上编译测试通过的容器,批量部署于生产环境,包括虚拟机、裸机、linux下源码安装OpenStack 集群、云端、数据中心等基础应用平台。容器完全使用沙箱机制,相互之间无任何接口。本文将介绍 Docker 的九种用法,以提升生产力。
1. 本地依赖(Local Dependency)
在本地系统快速尝试 Magento 或使用 MySQL?或是尝试大部分开源项目?使用 Docker 可以节省大量时间。它能提升开发效率,快速搭建开发环境。
2. 搭建环境(Build Environment)
如果希望构建源码,但发现没有合适的环境,使用 Docker 是个不错的选择。它能将运行环境和配置放入代码中,部署时可在不同环境中使用,降低硬件要求与应用环境之间的耦合度。
3. 微服务(Microservices)
微服务架构将一个整体式应用拆分为松耦合的单个服务。使用 Docker 将每个服务打包为镜像,并用 docker-compose 模拟生产环境。虽然实践初期可能费时费力,但长远来看,将产生巨大的生产力。
4. 自动测试(Automated testing)
如何编写自动化的集成测试用例?在 Docker 中运行测试用例,将测试用例与镜像紧密运行,编写测试用例时将具有优势。
5. 部署过程(Deployment process)
使用 Docker 镜像进行自我部署。许多主流的主机提供商支持托管 Docker,只需设置 Docker,并在指定端口运行镜像。
6. 持续部署(Continuous Deployment)
Docker 适合持续集成/持续部署,使用 Docker,持续部署变得简单,新镜像将重新开始。
7. 多租户环境(Multi-tenancy)
Docker 在多租户应用中,可以避免关键应用的重写。使用 Docker 为每个租户的应用层多个实例创建隔离环境,简单且成本低廉。
8. 来自一台机器的多个 APP(Multiple apps from one machine)
Docker 可管理单台机器上的所有服务。使用文件夹挂载为每个基于数据的 Docker 镜像保留数据。
9. 扩容 QPS(Scaling QPS)Docker 通过创建另一个容器轻松进行水平扩展。在遇到高峰流量时,Docker 可帮助解决问题,只需添加更多机器并增加负载均衡器背后的容器数量。
简简单单将Java应用封装成Docker镜像
想必Docker这个词大家都不陌生,是一个非常优秀的虚拟化容器。我的博客
怎么把Java应用打包成Docker镜像?对熟悉Docker的同学这应该是一个很简单的问题,把项目打包成JAR包然后在Dockerfile里用ADD命令把JAR文件放到镜像里,启动命令设置执行这个JAR文件即可。
可是对于不懂Java的,听起来貌似并不是那么简单。
在这之前,我们先了解了解什么是:Dockerfile。
DockerfileDockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
比如一个使用Maven构建的Spring应用就可以用下面这个Dockerfile构建镜像。
FROM openjdk:8-jre ADD target/*.jar /application.jar ENTRYPOINT ["java", "-jar","/application.jar"]咦?这是啥语言,也没见过啊?这个其实是dockerfile的指令。
上面这个Dockerfile的指令很好理解,使用Maven构建的Java项目的目录结构统一是:
project │ pom.xml └───src // 源文件目录 │ │ │ └───main │ ││ └───java │└───target // class和jar文件的目录用mvn clean package打包后会把JAR文件生成在target目录里,通过java -jar命令即可执行编译好的程序。
所以上面的Dockerfile里就进行了把JAR从target目录里添加到Docker镜像中以及将jar -jar /application.jar 设置成容器的启动命令这两步操作。
不过除了这种最原始的方法外我们还可以使用Maven的一些插件,或者Docker的多阶段打包功能来完成把Java应用打包成Docker镜像的动作。
Maven插件构建镜像Spotify公司的dockerfile-maven-plugin和Google公司出品的jib-maven-plugin是两款比较有名的插件,下面简单介绍一下dockerfile-maven-plugin的配置和使用。
其实使用方法很简单,我们在POM文件里引入这个plugin,并结合上面那个Dockerfile就能让插件帮助我们完成应用镜像的打包。
<groupId>com.example</groupId> <artifactId>hello-spring</artifactId> <version>0.0.1-SNAPSHOT</version> <name>helloworld</name> <plugin><groupId>com.spotify</groupId><artifactId>dockerfile-maven-plugin</artifactId><version>1.4.</version><executions> <execution> <id>default</id> <goals> <goal>build</goal> <goal>push</goal> </goals> </execution> </executions> <configuration> <repository>${ docker.registry.url}/${ image.prefix}/${ artifactId}</repository> <tag>${ project.version}</tag> <buildArgs> <JAR_FILE>${ project.build.finalName}.jar</JAR_FILE> </buildArgs> </configuration> </plugin>插件里使用的docker.registry.url和image.prefix是我单独为Docker的镜像仓库设置的属性。
<properties><java.version>1.8</java.version> <image.prefix>kevinyan</image.prefix> <docker.registry.url></private.registry.url> </properties>这里可以随意设置成私有仓库的远程地址和镜像前缀,比如在阿里云的镜像服务上创建一个叫docker-demo的空间,上面的属性就需要这样配置:
<properties> <java.version>1.8</java.version> <image.prefix>docker-demo</image.prefix> <docker.registry.url>registry.cn-beijing.aliyuncs.com</docker.registry.url> </properties>在POM文件里配置好插件后伴随着我们打包应用执行mvc clean package操作时dockerfile-maven-plugin就会自动根据我们的配置打包好一个叫做kevinyan/hello-spring:0.0.1-SNAPSHOT的Docker镜像。
dockerfile-maven-plugin除了能帮助我们打包应用镜像外还可以让它帮助我们把镜像push到远端仓库,不过我觉得用处不大,感兴趣的同学可以去网上搜搜看这部分功能怎么配置。
Docker的多阶段构建打包镜像上面介绍了使用Maven插件帮助我们打包Java应用的镜像,其实我们还可以把mvn clean package这一步也交给Docker来完成。当然把Java应用的源码放在Docker镜像里再编译打包在发布出去肯定是有问题的,我们知道在Dockerfile里每个指令ADD、RUN这些都是在单独的层上进行,指令越多会造成镜像越大,而且包含Java项目的源码也是一种风险。
不过好在后来Docker支持了多阶段构建,允许我们在一个Dockerfile里定义多个构建阶段,先拉起一个容器完成用于的构建,比如说我们可以在这个阶段里完成JAR的打包,然后第二个阶段重新使用一个jre镜像把上阶段打包好的JAR文件拷贝到新的镜像里。
使用下面的Dockerfile可以通过多阶段构建完成Java应用的Docker镜像打包。
# Dockerfile也可以不放在项目目录下,通过 -f 指定Dockerfile的位置,比如在项目根下执行以下命令docker build -t <some tag> -f <dirPath/Dockerfile> .FROM kevinyan/aliyun-mvn:0.0.1 AS MAVEN_BUILDCOPY pom.xml /build/ COPY src /build/srcWORKDIR /build/ # mount anonymous host directory as .m2 storage for contianerVOLUME /root/.m2RUN mvn clean package -Dmaven.test.skip=true --quietFROM openjdk:8-jre COPY --from=MAVEN_BUILD /build/target/*.jar /app/application.jarENTRYPOINT ["java", "-jar", "/app/application.jar"]上面我们用的这些Dockerfile也可以不用放在项目的根目录里,现在已经支持通过 -f 指定Dockerfile的位置,比如在项目根下执行以下命令完成镜像的打包。
docker build -t kevinyan/hello-spring:0.0.1 -f <dirPath/Dockerfile> .上面第一个镜像是我自己做的,因为Maven官方的镜像的远程仓库慢的一批,只能自己包装一下走阿里云的镜像源了。试了试速度也不快,主要是随随便便一个Spring项目依赖就太多了。大家如果这块有什么加快Docker 构建速度的方法也可以留言一起讨论讨论。
不可否认用多阶段构建打出来的Go镜像基本上是M左右,但是Spring的应用随随便便就是上百兆,这个对容器的构建速度、网络传输成本是有影响的,那么Spring应用的镜像怎么瘦身呢,这个就留到以后的文章进行探讨了。
原文:/post/为Python应用选择最好的Docker镜像
在Python应用的部署过程中,选择适合的Docker镜像是一项关键任务。早期,virtualenvwrapper曾是Python包管理的常用工具,但随着Python 3的普及,venv逐渐成为首选。然而,随着项目复杂性的提升,Docker的重要性日益凸显,尤其是在集成Redis消息队列和Psycopg PostgreSQL数据库等场景下。
在构建Docker镜像时,我们通常从基础镜像如Alpine、Ubuntu、CentOS或Debian出发。然而,选择哪一种并非易事。首先,我们需要考虑镜像是否提供长期支持(LTS),以确保软件的稳定性和维护周期。长期支持意味着软件更新更可靠,且降低了部署风险和中断时间。
对于Ubuntu、CentOS和Debian等传统发行版,它们虽然历史悠久,但预装的Python版本可能不更新。例如,Ubuntu .可能预装的是Python 3.6,而最新的稳定版已经是3.8。为获取最新Python,可能需要自行编译安装,这在某些版本中是必要的,如在CentOS 8中安装Python 3.8。
另一种选择是Docker官方的Python镜像,提供了多个Python版本供选择,这便于管理,但需注意不同版本间可能存在差异。Amazon Linux 2作为云计算环境下的Linux发行版,是AWS官方推荐的,提供了LTS支持和针对性优化,适合生产环境部署。
Alpine由于其轻量级特性,常被用于寻求最小化镜像空间的需求。然而,由于它使用musl库而非glibc,可能导致pip安装的一些依赖无法直接安装,需要源码编译,这使得Alpine的构建时间显著增加,对大规模部署不利。
综上所述,选择Docker镜像时,需综合考虑支持、镜像大小、构建时间等因素。虽然Alpine在某些情况下可能表现出色,但在生产环境中,考虑到稳定性、长期支持和构建效率,可能还是选择长期支持版本的Linux发行版或官方Python镜像更为合适。实际选择时,根据项目具体需求和限制进行细致评估是关键。
Docker 安装及镜像管理
Docker 安装及镜像管理
安装Docker首先需要下载docker源,通常我们会选择修改源地址以从清华源加速下载,以提高下载速度,比如使用阿里云镜像加速。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`并指定导入路径。