From 9dbc080302017f52bbd094a445aefae9d47df312 Mon Sep 17 00:00:00 2001 From: yuchengen Date: Thu, 28 May 2026 17:22:58 +0800 Subject: [PATCH] feat: add MLflow 3.9.0/3.10.0/3.10.1/3.11.0 container image for OC9 --- frameworks/MLflow/3.10.0/Dockerfile | 26 ++++ frameworks/MLflow/3.10.0/README.md | 189 +++++++++++++++++++++++ frameworks/MLflow/3.10.0/build.conf | 4 + frameworks/MLflow/3.10.0/test.sh | 77 +++++++++ frameworks/MLflow/3.10.0/test_result.png | Bin 0 -> 18922 bytes frameworks/MLflow/3.10.1/Dockerfile | 25 +++ frameworks/MLflow/3.10.1/README.md | 189 +++++++++++++++++++++++ frameworks/MLflow/3.10.1/build.conf | 4 + frameworks/MLflow/3.10.1/test.sh | 77 +++++++++ frameworks/MLflow/3.10.1/test_result.png | Bin 0 -> 18925 bytes frameworks/MLflow/3.11.0/Dockerfile | 25 +++ frameworks/MLflow/3.11.0/README.md | 189 +++++++++++++++++++++++ frameworks/MLflow/3.11.0/build.conf | 4 + frameworks/MLflow/3.11.0/test.sh | 77 +++++++++ frameworks/MLflow/3.11.0/test_result.png | Bin 0 -> 18850 bytes frameworks/MLflow/3.9.0/Dockerfile | 26 ++++ frameworks/MLflow/3.9.0/README.md | 189 +++++++++++++++++++++++ frameworks/MLflow/3.9.0/build.conf | 4 + frameworks/MLflow/3.9.0/test.sh | 77 +++++++++ frameworks/MLflow/3.9.0/test_result.png | Bin 0 -> 18702 bytes 20 files changed, 1182 insertions(+) create mode 100644 frameworks/MLflow/3.10.0/Dockerfile create mode 100644 frameworks/MLflow/3.10.0/README.md create mode 100644 frameworks/MLflow/3.10.0/build.conf create mode 100644 frameworks/MLflow/3.10.0/test.sh create mode 100644 frameworks/MLflow/3.10.0/test_result.png create mode 100644 frameworks/MLflow/3.10.1/Dockerfile create mode 100644 frameworks/MLflow/3.10.1/README.md create mode 100644 frameworks/MLflow/3.10.1/build.conf create mode 100644 frameworks/MLflow/3.10.1/test.sh create mode 100644 frameworks/MLflow/3.10.1/test_result.png create mode 100644 frameworks/MLflow/3.11.0/Dockerfile create mode 100644 frameworks/MLflow/3.11.0/README.md create mode 100644 frameworks/MLflow/3.11.0/build.conf create mode 100644 frameworks/MLflow/3.11.0/test.sh create mode 100644 frameworks/MLflow/3.11.0/test_result.png create mode 100644 frameworks/MLflow/3.9.0/Dockerfile create mode 100644 frameworks/MLflow/3.9.0/README.md create mode 100644 frameworks/MLflow/3.9.0/build.conf create mode 100644 frameworks/MLflow/3.9.0/test.sh create mode 100644 frameworks/MLflow/3.9.0/test_result.png diff --git a/frameworks/MLflow/3.10.0/Dockerfile b/frameworks/MLflow/3.10.0/Dockerfile new file mode 100644 index 0000000..49d3aea --- /dev/null +++ b/frameworks/MLflow/3.10.0/Dockerfile @@ -0,0 +1,26 @@ +FROM opencloudos/opencloudos9-minimal:latest + +LABEL maintainer="stronking 363133710@qq.com" +LABEL org.opencontainers.image.source="https://gitee.com/OpenCloudOS/ai-agent-container" +LABEL org.opencontainers.image.description="MLflow 3.10.0 container image based on OpenCloudOS 9" + +ARG MLFLOW_VERSION=3.10.0 + +ENV LANG=en_US.UTF-8 +ENV LC_ALL=en_US.UTF-8 +ENV PYTHONUNBUFFERED=1 + +# Install MLflow +RUN python3 -m ensurepip +RUN --mount=type=cache,id=pip-cache-opencloudos9-cu128,target=/root/.cache/pip pip3 install mlflow==$MLFLOW_VERSION + +# Default MLflow configuration +ENV MLFLOW_HOST=0.0.0.0 +ENV MLFLOW_PORT=5000 + +EXPOSE 5000 + +WORKDIR /workspace + +CMD ["sh", "-c", "mlflow server --host ${MLFLOW_HOST} --port ${MLFLOW_PORT}"] + diff --git a/frameworks/MLflow/3.10.0/README.md b/frameworks/MLflow/3.10.0/README.md new file mode 100644 index 0000000..bf4cc1b --- /dev/null +++ b/frameworks/MLflow/3.10.0/README.md @@ -0,0 +1,189 @@ + +# MLflow on OpenCloudOS 9 + +## 基本信息 + +- **框架版本**:v3.10.0 +- **基础镜像**:opencloudos9-minimal +- **Python 版本**:3.11 +- **CUDA 版本**:N/A + +--- + +## 项目简介 + +[MLflow](https://github.com/mlflow/mlflow) 是一个开源的机器学习生命周期管理平台,主要提供以下能力: + +- 实验追踪(Experiment Tracking) +- 参数与指标记录 +- Artifact 管理 +- 模型注册(Model Registry) +- 模型部署(Serving) + +本镜像基于 OpenCloudOS 9 构建,提供轻量级 MLflow Tracking Server 运行环境。 + +--- + +## 构建 + +```bash +docker build -t oc9-mlflow:3.10.0 . +```` + +--- + +## 使用示例 + +### 查看 MLflow 版本 + +```bash +docker run --rm oc9-mlflow:3.10.0 \ + python3 -c "import mlflow; print(mlflow.__version__)" +``` + +--- + +## 启动 MLflow Tracking Server + +```bash +docker run -d \ + --name mlflow \ + -p 5000:5000 \ + oc9-mlflow:3.10.0 +``` + +访问: + +```text +http://localhost:5000 +``` + +--- + +## 持久化实验数据 + +默认情况下,容器中的实验数据会随着容器删除而丢失。 + +推荐挂载数据目录: + +```bash +docker run -d \ + --name mlflow \ + -p 5000:5000 \ + -v $(pwd)/mlruns:/mlruns \ + oc9-mlflow:3.10.0 \ + sh -c "mlflow server \ + --backend-store-uri sqlite:///mlruns/mlflow.db \ + --default-artifact-root /mlruns \ + --host 0.0.0.0 \ + --port 5000" +``` + +目录说明: + +```text +mlruns/ +├── mlflow.db +└── artifacts +``` + +--- + +## 实验追踪示例 + +创建示例脚本: + +```python +import mlflow +import random + +mlflow.set_tracking_uri("http://127.0.0.1:5000") +mlflow.set_experiment("demo-experiment") + +with mlflow.start_run(): + + mlflow.log_param("learning_rate", 0.01) + mlflow.log_param("epochs", 10) + + for step in range(10): + loss = 1.0 / (step + 1) + accuracy = 0.8 + random.random() * 0.1 + + mlflow.log_metric("loss", loss, step=step) + mlflow.log_metric("accuracy", accuracy, step=step) + + with open("result.txt", "w") as f: + f.write("training completed") + + mlflow.log_artifact("result.txt") +``` + +运行: + +```bash +python3 train.py +``` + +然后访问: + +```text +http://localhost:5000 +``` + +即可查看实验参数、指标和 Artifact。 + +--- + +## 容器网络使用示例 + +如果训练任务运行在其他容器中,建议使用 Docker Network。 + +创建网络: + +```bash +docker network create mlflow-net +``` + +启动 MLflow: + +```bash +docker run -d \ + --name mlflow \ + --network mlflow-net \ + -p 5000:5000 \ + oc9-mlflow:3.10.0 +``` + +训练容器中配置: + +```bash +export MLFLOW_TRACKING_URI=http://mlflow:5000 +``` + +--- + +## 默认配置 + +| 配置项 | 默认值 | +| ----------------- | ---------- | +| Host | 0.0.0.0 | +| Port | 5000 | +| Working Directory | /workspace | + +--- + +## 已知问题 + +* 当前镜像为轻量版,不包含 PyTorch、TensorFlow 等深度学习框架 +* 不包含 CUDA 与 GPU 运行环境 +* Model Serving 场景下,部分依赖需用户自行安装 + +--- + +## 上游项目 + +* MLflow: https://github.com/mlflow/mlflow +* OpenCloudOS: https://gitee.com/OpenCloudOS + +``` +``` diff --git a/frameworks/MLflow/3.10.0/build.conf b/frameworks/MLflow/3.10.0/build.conf new file mode 100644 index 0000000..1be4352 --- /dev/null +++ b/frameworks/MLflow/3.10.0/build.conf @@ -0,0 +1,4 @@ +# MLflow 3.10.0 on OpenCloudOS 9 +IMAGE_NAME=oc9-mlflow +IMAGE_TAG=3.10.0 +GPU_TEST=false \ No newline at end of file diff --git a/frameworks/MLflow/3.10.0/test.sh b/frameworks/MLflow/3.10.0/test.sh new file mode 100644 index 0000000..1cb9a5c --- /dev/null +++ b/frameworks/MLflow/3.10.0/test.sh @@ -0,0 +1,77 @@ +#!/bin/bash +set -e + +IMAGE="${1:?ERROR: 缺少镜像参数。用法: bash test.sh }" + +DOCKER_CMD="docker run --rm -e GIT_PYTHON_REFRESH=quiet" + +echo "=== MLflow 基础功能测试 ===" + +echo -n "检查 MLflow import 和版本... " +$DOCKER_CMD "$IMAGE" python3 -c "import mlflow; print(mlflow.__version__)" >/tmp/mlflow_import.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_import.log; exit 1; } + +echo -n "检查 MLflow CLI... " +$DOCKER_CMD "$IMAGE" mlflow --version >/tmp/mlflow_cli.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_cli.log; exit 1; } + +echo -n "检查实验追踪核心功能... " +$DOCKER_CMD "$IMAGE" python3 -c " +import os +import tempfile +import mlflow + +tmpdir = tempfile.mkdtemp() +db_path = os.path.join(tmpdir, 'mlflow.db') + +mlflow.set_tracking_uri('sqlite:///' + db_path) +mlflow.set_experiment('ci-test-experiment') + +with mlflow.start_run(): + mlflow.log_param('learning_rate', 0.01) + mlflow.log_metric('accuracy', 0.95) + + run = mlflow.active_run() + assert run is not None + assert run.info.run_id is not None + +print('MLflow experiment tracking works') +" >/tmp/mlflow_tracking.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_tracking.log; exit 1; } + +echo -n "检查 MLflow Tracking Server 启动... " +$DOCKER_CMD "$IMAGE" bash -c " +set -e + +TMPDIR=\$(mktemp -d) + +mlflow server \ + --backend-store-uri sqlite:///\$TMPDIR/mlflow.db \ + --default-artifact-root \$TMPDIR/artifacts \ + --host 127.0.0.1 \ + --port 5000 >/tmp/mlflow_server.log 2>&1 & + +PID=\$! + +for i in \$(seq 1 60); do + if curl -fs http://127.0.0.1:5000/health >/dev/null 2>&1; then + kill \$PID + wait \$PID 2>/dev/null || true + exit 0 + fi + + if ! kill -0 \$PID 2>/dev/null; then + cat /tmp/mlflow_server.log + exit 1 + fi + + sleep 1 +done + +cat /tmp/mlflow_server.log +kill \$PID 2>/dev/null || true +exit 1 +" >/tmp/mlflow_server_check.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_server_check.log; exit 1; } + +echo "=== 所有测试通过 ===" \ No newline at end of file diff --git a/frameworks/MLflow/3.10.0/test_result.png b/frameworks/MLflow/3.10.0/test_result.png new file mode 100644 index 0000000000000000000000000000000000000000..5449a8809532041e160e80a0923f118186d2a96e GIT binary patch literal 18922 zcmb4qbySpZ*Dgq>fP}R4NJ=Bk&>%2FcQ*`3r_$Y>3PZ@y(v3)Wm!x!~fRxl3aK5g=t*985Ay1Ox;ec{wRn1O((p_~&=%kKjKA_B7KF z5ag@mr6kln4UgV^db1&XcI1d?-6`FO?2(IE?;rDy#SNxTvw@SsBE$a)^;lSd!zzrs zBRtPS=k&ef*T>Sg%Xna6u{2;R4$sYL`MGy6#W0QG zl6NS)UjUC;-|{H2$O;4dYb2p^e6*K*8Rv{syX4j7Wsu@yc~csxaIqFChZ$z|&Cxb4 zKw|odSNn;Po|p~?*tHS!b#Azf+w*u(&Icy}3K`A=Tc~IGiF42D>gt`2Gu`pG6$d0d z?)%&8AQ?AdD#$pubJAz%0SqE=X~-Mtuo2q3np7IRu2fOIwM{CDKBiZhBC>UV7qt}Z zgWl87!0(D6@d3oa!68toBo#kv)~68TI5Ch)v0E_Geqm;7%~(iOd^GK#6u^IfZ?U9#A~jkL|O9(u4i(M782dpNoWBMr{RI9*}WUqebhM zoX4U3t|7%jZDva@7~l4;{5VQ(zfJ})NVLRTaMPHYgDjn$PdLZY5HNc%HdEpF@``Nf{Y=|>{&UXkbPEV>Wo_^9r(H>i zDrm1bLW!F+?N)2_6uj)*Z88d^kkI_ol)Y&P(>QON6L8Q3njOT+cJGdKspXi zDU?~xE@fC?|=Re2uGBLE%^X?^3l_t!ZUWQL70cM#?o=`9eb+*-0 zaf1y@;NBlH&1bKT$oel@HZ~cO%Wa3{(C`5*ntdLeh2K7SYZC+Uxw=LTUethX=L7@3PozcB5gSEDt7rKh>w0SLVxlGFb~6M&{d9K}Ws$s!70T zDUe0iKTcf52rH`~0dZ%G)Q3ALIc=}+GD_^6WO~{YeV=clIYL9TMp7fEd`&Q$7n`4P zxoS#Q!5UvHiKjO6K7Sf1F{s{fvzSvBN6$>b4G*!8gd2IHGp(NE(TUi?O0;b&Cl^vT zaUQ)yp_L5f-Ab_tzFbD*_S-dDnw}LySxhN0jJhBx2#=QR$Mcc>Wrbv zOP(e9++qr6D$Os9gf8r#Jw?>ASYn5c3@Zdga+1ug7uTQ=-;ZBn$vT)?ywVD?D(%Tx zM&w!(8a>pBpT5MjlG#8F$3bwtaZX%=8N#NmyV;R8CR`Y-==-(=GKvoKqXK=KiDOaG zZYgk{E4ZpdLgkswLq5HzI}lMMFd>{SKb4jZux^#E7OWc)6*YdvbK08y$Ru!%(uGx? znUcBa;6ZjGc0SX6TIw?lu@Sq-V(uU@4#8r4n-{{fVH%3Dj6L+hJHSB*IUigbyAwvo z9!p+0hn|8XvFu&GXVl_~sz+7lC&KzxdSXU`Lq0_O^ModG8Vkc;q8ffT5fXvgwLflRH|i38MBfdmxATlim*Zkk02?g0T44bZIqH+&4F`1RW9TS?R&0@lfP9Jfk>s7W!?c4i#*+ z)Xj!AF8RCS`mP?6G{sA9vJ$#dJQ&?krwfLqHI5?aIFe7=haa{PRcsTp=_MOInyV=n z)IV;PI8X&tHZR|rE;i0acaul>$XcXKgEMEK0e0mW0d@#4-p<`8?Wkm#BfZK>#Fjl@ zD5SgS_bf>Kl>Y4Pu%0e%IUPL-LlvH=RBg5XqDm+s!v*0q(ErOv_-@Jko{ViCqb%3v zGw;Nz=ADR-%5{nzeX1|RA&HR50}Yt3-n*cMekR9|XQnXgzayd=i|NovC4;|}5(;!Z zpHX)b)gQaaaE?474k4eqOWW>KFrut|zHByPms!QH^RMP&;@* z%vQ>}8cX-Zw&}&jIF;vgz`?Q?k875fPNoT)R9k_R{z88{cn8}JPbx?*Fy2qKvVycw z1C7$g@m>}mBVmT;vEWrP8NoYEwVBs_1ZK@`yM=5s3!*mUg1CpI$)y=)S5vh&?;ldM zHRTs+c0UBN{9t00>P&}n;gIpY?etWCk^ruwm&9X}`t*@_y&_^`30vx;4VyfOCm&fh z#lquhMuNH*my1LMD6Q)fhWIRnkNoCIUnX(`GLJpp!3_ z(S100bgozx~Z|Yci9LP9*1NCuwHy`{jOv}=1)J^<)y0M=}t|A zv0oMIR%Hd%6=0{n;XSJLjd}$cvos_Z*qdjY$vtuoe}P$D=y5Q^n~yw}GtADohxC-u zwk6jyHe?ci3MXnb8o$2}M|NCrtpGJ$H>=Z(0$uaCymCg*2gw$ixd+9D<5vjFsbFO*a zWxTKrt3%6UuuOIe#gGqO+}G$kdSL_1zc%4wT}<^4n&*2>`9N&e$OkAU!BqOGHM((G zDcgnBW2%Yo$9tE1B;dpnIG#w@^fdmyr9LmbiI9rSMy-aFc6Xi%(5uMx=P{d*mqH9|vl*->M=T5qHs-{yzLjDyKpHn1gX z@h;{S{ZailmZB3c(&z!1;J|$Q%Hffx8eUxGa~6iZI2}E;6*8e@>OiJQI3zAFnY0*k z;x1)*ENa7vFe)uxAAqb+lZRIMuzccbvi7IfiYT&Hw?Ku}Ry0>|9r*&Z1u&XEp`k3- z+*JB@l20>}^E8y9ng2P9Q*v*#rN09bLOFwbpbTm3ex0K1VYg>@!uZ?;mrDUq#Yx$P zF@`nxF_BiwMEs-X*pjvzq0#8pB6|F0iBV%cSwg{c3iw?V8b4ph5k^( zJ>WpTbBJ5pU;rQ9HV%`Jm-l_}*16=$nq*%buqTjoX|L79Bh3Qm2!-5 zSxvj1NKj5z!C}K^n^DdmGG1$6{BX8rrqCza9o#^<{40763Cv8t_up4ZpBU+0xlIf; z=&hj+YsqqF3%2*CLTU{8D!`wQ%%mqHVZg1hz`~IUooCiVdVORM%}4cD7Ytv_5zuTf zYn@aUDbbo7NvhDwl*GgFU?hJc1@%l%dt$;o9ArXQGorrt|K?hfIe=gqJFA|~hZKwD`oQ8>J;vJmck*G7D zrJo~V4HbU=Ty06nws!Auz&ni>F`;Un-KC2qI=QUT zCJ}aTNHevP0=XvdgHhOCxH1UTY>D!MYQT&2%eRrYL`oJMo9!uEp=N9b5yJ3bf&<~rywK*B7tF;(tAtbB^-!pI~#lo*GZd}Vl~5B zgPGl+o!DFxBqWexqAHZXYvYU#l(C$4s(dv(A6IHm?r-SeHU~q@E$Se^E?XE)pb^B< zb>!_jh8f;C@vAhy*YLP;1LDU}8}}!^QpRyhlX3ZF&Pt_LC5YukXq>RPNXCNL-!0teKSI{qdB@4# zC-MYUh9H^)s})2*&U#g!~tw=K@YrEwWC1-8ACD5j`bK~#A*RSDKHp2j^>*R}9Sc?=;y%HB}~VBzQqh3C!jkG-h+ zZgDM!GzvE0Cd|5+u0Pz7h#(Ee(63}Q<4$C5K}G0s$kJ>;Om@%NHRLcyKiAMJ{9yu8 zt>il1mY)+!e_)O#F_4H;Oi#sHuo%bR@9@;qc{z)vI|=2Y8F;NHv@|>7BD378Z%a-F zDTH5Ag3E0SH%g+c_@feeB!m;0cq@St5=GcsQbrtU=gA0vcTEjPr^w z>pU!N$6*o8>J??J2V1VP{#*`c5v0b+G=X_ON!a{zcGI|uu(a5`>)Ve*Jx=-2J_=1* z504DS#C~O&KY>-Xv%a|0x625bbTR=3J`S5^@l1$aBRg5$Wc4X^Y%?NWcv#fk(U8WL z;;rrTl5O@zqlUbv*N{{OCo2?(YEPF9$4AGj_pH~CsA>>}pQ#+diuepOhHD&w{bL_E z2svx2#xO*KM2QeY(}gi6sg6IKHT>se>47Kp=Yg=6Mc>`}-qql=`sW*CktF1aV`u(2 zUpc*OWku>vFyW=P2V5*@quqm|Kf^?p3hv5+m`~Xkm^eBO9RXBMbnM%;5!c7!f>6IR zMtCKzU#t@d7~K52v_iOl&l!OSq(X*Q@hrq1)V}Pw3R1=C^FM=s>t5%lo(jg_8s2RU z2te?svWKoC4!wGQp=T8Qw22R6rFLx$b)6;R?9!!d;E7{(U8VZ02fOT7+C!@|lfU)9 zu+4~&^-;g`$8TMJSFvf0JjaQ0_~hb3bEi^6fndTI zUVv)}h4l#^?SSp(zNUWLEFy9wGodFuUnan`^#B8CA8lrDmQh1W%cbtxEo^40FibE~ z5zpyWV}ea>(pV!Wxv-@DQh%2%@lHE@KY_YE1Xfm8Ph1K?-2|GKX5=JOEAge8gaO%c zkFa-IfcW!CYT5^C`o1$T+I^{>H73&%n9BtKFOrr6|49=A+dnK3pX@0 z9BfUzzPJe0&2^2K9iib;l_>d1;r61$&|a z=s{j^fiwi`6y?vJfvUv7le#u1`f9s}$?Y+|(`Q*;$Vr|O$>f`n$_KKhDuWBW_dKsz z#m@sAbiomIM-9ohaeZb6_eD9kL?S^Co~&o8MMKb``#~aUz>F#32Nk}WS9AE0nMmP4 zd<&hgdR8@xDENS$a*{{{{6kVaoEEvsyn2-DN59I#k7Gn0-pQ*CHkwpGs8Y~fS7Y_}bkJR{v>d+7z^i5_!eVyJo~tJb=feNE z>Gk~scsgg5g%IjDy2CxZ+pfaq7G8HoW!hksPeKG zlO|S7RMhm89c0=}VU@Ddjxk{k#caJx0alH6SoTYkBa$v~4@Ac5YFEtU5&%+Cn!(OJ?WW7;I7zr3Esg`u?nPfyG(IN~`g!w2%Rm~2xCV;wo7XXBh z&$RgMxBmfyEvFD#`p6y`<>2+9A*=#p$RKD-;qvUMh2dQiy|?h-OD2Un^nL9LBd|KW z3Ryn@JfO}dEe8lfcPUE6)?E65Su=8g1?wvvtCumhz~)8uzYj*+6be~an@Xup(04J# zs8G}byicX}bmhB^nR|*M?XhxKcIL;Xc}7OHtH=8sQ#$)gL)vP`Q!S_Db*blnO~wfY z`AU^BFGe$q1Nc+iwR!8T30Uu5>R1QylurfNT_n>&^}^`?tS9{Je{?ne103c4`mOnA zEsP%CN(6>K|A2Su?;4zUXBm`NS?9VV3j&A=T_wxeV;KB!Zt;LIdrBz#%EoS3@sJk- z4M*6UN?Y0zf8W1&4%2c__6LkXn)W(X-VU;6=JoAxdB6KxiHN?930=>Vt!#d&!8d+> zmsZqIZ-DB;gyCr|iiDBYY?1Xa;jSDS!ZjHRJthHtr7f#Tf&X}F3Me^(V{}(S8RCs? zbbV%W(D6#QF7hrS`^}@S#ljWaaaKPgQ6@PCr1dk-om<`qZiME8LAB&^Fiz&@A^AT7oHpB>h3f^n{{PhL_Yc3s)7bZ4C-bhO~b~x<8`b35x z`OoR;P3VAYRq@Vr8|YCOEXQ``HAqS*2D1k=YV^8gC-Uk({zhRCV7R}hRxH{sWPO@A zfKq#?IS5pClqYt|o4J5$?{`5^i6h`5>D)mi{W}Ocs|W&5rU7R^3q;a-gY6J-y_Gnv8$Fsl%ID|$EL`8jU5CiB ztyt@6YC=0_$#d^kGhpgUn)XY+L6!Bf~41q{0l@w~aZ0-Tkk4Sj|_5Ma#hd6@$;@}-_* zIV&HaaEp>@O2)EEy$7KDR3MmTWKwjpI6Uz=6Krd_XBTT zn{lCh)`g<#-wTYnD$U?k^NHZvACh|9wN40938E?Dq7fyx?8+>}Nkr%KG{RP3Q-|5H z3M9it>OU0c8ru*c7$Gpi65tKW?60au+1=#8HaEGokq?ylD%hDW$dOZl9~o}6Qy)M-RsE%VO8_P{vV=Jb5d9Vx zDJjewKJqr0C~}$XXo^VMxGn9H;}4;77y<&0$=wx7`c67H1s@+Kd*GZW1m^`uzJHlB z_9FjAbcVfO!EeO~VA^2LZyikJS+Wk_Q+f%flW~^P4__ON8r$&*N%@;LU3@(+MebK* z9Y0Ctb)nj5QejeJeeeIkQ9tGPoIZewf^OF2_+3Cep5N5)?R{W*(a*C`U{$E!+pdA* z-qB*nCn?wO6%xY=e8^ zOoWPf1H|A%x~+OPKw##eQLAJ>T3i(n{A9t*t*+<#%VdnoA1jlrHM~!KMp%yeday6C z(owm|6HEUZGGa% z)Z@bo7FaQ8y12%ajtK}3eiEz+X;v({&yQ0%%z6=8(QyK>8tU)l1>%oZj@0w zede%I5$!8;5E*+8JTVDy`R?(?VA`fA^zko#k504MZVpUXN(v*0)H-Pi*iiFPf}zs` zB=2MuKyz#ZqP(gS210FD*wSrPjvNV-X4H-Y-gkfTnNJXy;EOfJLim^Zi(zB-$OZrt zes2!%^x1#p0pB%%CuprHf5RK_UP%yGb;Ct|gF3_u0^F6Kl5H6UXIS;_rFN6s4tf$6r2w_I2Q#goOQh ze7w*{1;BpT=^@D(f$fx8j+YRYD+=+8s`O&9gc=oNPamJsqplyn;?;h~zv2~3wvf5#_8lkLXz3&!xuXZX_8ks}{v)$QbQ@Wj56*A3WH+{k&L zY59%RtHLDip2r}U_Q58s8Ax-|KQ#hG5_A8)RAp{Wo^|0f%WH?0=gDy*`Aiy%Fc7N? zqt?hdKDBhzQm5!-3J?s0zMzBW9l^!rIJ!0kxcX-PZW|5Ub!>h2hYW_~R1gSiJZp_Cl#hQ&A#*~R2D7I zSuj-abAJW-DTTN7LGOtRJjU#c(P9b^=l&GuFNbw65VzAmY@EP|q@br-C82+_g3p2K zv|Mk*^X>d4?S3AKGkfF^YJa#UMWoL$cvau0TC9CJ)hbDp=W2D)xXl*%*9YA^q2U=K zAHHcRO;z=#zfQT5@NG?%AzUDXHae2)(`ov+P62o3m!Ve?lhQK4wPz-6>i8*XqPY{i z9Zpr@Ely6?(|L&;qB}Ck$={K>CY>i3{U&!E@;)#C*I_g1hOUPvHd=R4WE$pzCPJ^t9mRN_2eEd zWuP)7)8%)drMh=x0;76_f8F!oHDipWPjK!-f7`)fYpEa1+eNg(E0ud zkgu0l0AZODX$ju`TdMrwMG&-Fz0<}4qq4Fx>_YijGD9SOCKG2nx%pW)Gqqv+{yZ_y zBUQ*WYV+4eF~NC1KVyhB{t*4=z^mWC0+>>X0qaOzdlX=pZ>gH~&PxuWX6x)8l08!Z zf7!S%Zw83o9A}DWZ{e_~2(_8M#j#T9e;^_HwJ;_0A1=RX6#5SY0{b6f{$YV|pv7ue z04!)3{losfXn#Xs*4*5j;60wNc@`+zXh!d`=u?58Ka9%2HZm2J2`Jz8e^}w%tn{s~ zNqRUV8`AENRhU^UTu~-;2dD(-kKVm#6*0wRTj2EZkOBPEd@d=i(fhTvsy~G7dlQ%C zZsd{6s7;TmqFCg#1WX`_FTAlAkQih7-$m3eHwRs5U=VtPH)tL?6K53cxAA?0>d&Vp zzg2-39!7W0$i8I5?DROo>SN>%asN2mttWhL1IwE@Lr;>j*f?Hbpj9W$bzyYsVf(=C zqse(*IwF`=V!rXrZ8mJ6mP&r`nKCQvN3iKD?Nm}A6$`U&8Q)L>#kARSihS640n76G zdTBOsQn%-=)T{C#lY`l%tRNWyZ)D?%QtTg?c@`z~?uQG8>rsz6{*?|;%UDTIC`i1j zeAgQAzSinT!9FHYq{V2rQnkj4aje7GVh;F|($U$m=Ho``f~fV9(o0hb26SoiWEb=n zQWL(|cj->rQ0?K)J)4jFL=YFE;K9k9M%4s@i*-T8_JqAmww6IVq`Jj;3RgX>KlfEE zD;6ZoJIMN?Im%emN8FR%PA3(xX1F7*m|}k2O2HyV2C;1v&^(X<>8Ak*A=ad&W$EL( z49-Ip7BkPXqQE6|ULQ*9VtIj_C#duMU-d-x-o7RI{%Vd1BcDYhEe4ctbLNs}8FTs9 zVN5)s=!l`k+}$eKuVqa%*++_G*ZWi#&F}I+WoM!DYI-J;ql!omdZK}c5(G@B%^ymX zYnW6Z()fNy*A(W3QO3=%!tTkaD&`Z7qrE}^;TrKB=|O3lwnY7Cl7Y~-v6~wooHWL~ zIOf+?_j(iW8FED2M-javoT|!%V^`>YTY0l@BZT(DG;_SZb?3JeF3NDsq90OV!-^*c z^26bg0j=TvbwGSFBH|JmX}r-5Pp&L*6h8L^6J~I>5NSx>jC7%vkyd^|x9rzi{r4ji zCB-{*ocsrPI~BVkf1OtN7gvW7blOHN_&k>r&7qRVKddd2*>NTDZO)ZSk>`V|DRf}= z6u!QSDkqV8PC%^>_y6JR$rginLJsEiHnO{u%+P@%o&5nWYJ!PHtn!-mPm{1xaxc?r9UM4ajzd$ zesG2p@9J#VBV(;z@qPM6bv#9us-d9f8&|Ohk~}>;@{vPFT0)Hpnxwf42!@hsCZ|R5 z2uQ8`t$IXZ;iO=!us#}=-S^OKj3#S3*O0uCK|wrgP+CJn!|wfoNGcK)a)ww#OkR*|aC40@Vl>@{4kRnBv$Y+eKHJ7n{ z`9hywS_jKX&6ARZJ%Ja}918P5!s#dj|DxqZ&N=|y=A^?c<2eki(NT@)FC(eVr#5E$ zUPUJq%52(D07jK&G0K-$ws_pj7BInYq9N!JGJ%qgXAs(nl!ReTC%duv%n}|qB7DW> zL=F0-zP>Oaqk7aB|FmW;TV&l%IY5c9yAoFWU0&$l!{$!Jke;zOPzM?VKP3uK&TT5& zndnk8BynXNWkzZfsq8y1?G0X9b-n<*;=P@*#%3YhnzuLz&Qpv+@7Eavlw?p|cV?E7 zDX8D~+C>NF34MDjD&U=BSD6vh5hA|WsF3_8YMcfQ1h1#%{d|!|o8Gr5pqUoSL-bKq z)1`mLQK|6xczVPZGa*!Oy;GDE(0_1t@qdN1U*#$3R;$UJf7PeH!+VmK7JL_H1a`R~`mrG< zqf1@1Z#8c)3l_J(%^eZQVk>&c{Qau+n@Shxu4!25)|Lx+_Z=(_TKVQ4^!Y9m6gPSZ7Z{cu{_UNV$;s`zEUAkdQ(5B zH%nsvezKRjCWiD~eAgg{;Pi*SS?hHC^k~!V^3{$GmCeH^Pghn}=($9{#l}&$wzeLU zQv&592C$duG^XEc3*rM zqUt|7?-r6xaU>A_&zi4^ft>7#{jGSVEP^K~0t4A9X>_g!Hf@$&C4rODa|0(gH$rbK z2qR%3{nFGQX^(dB18Q@Mm8jRRqEc1o(50Pn0sIpfqF>!}6Z+2+Gb10yVmR1N>ZcWf z-Z9ewPiT!?_bO4gw`Pz*K|j^_*Yo7#O6XoH4oBT!{S%jj3EvS(v!HPDx(?BSOfRC} zt1H2PRl^zjyb@Brglx2EH*yKr(p5}QPB=)BTr~U7B3dMo2$)U zty(n0SS9t%{@jZ7OKHSWj_`81qjrve+Wt;U{u^#kE zfZZ~zd>*gCVNfNUlYYW}%{>M+D`B?$$U2+L&Za4RK80D#4N-GH7E3ovGpxVCriH$= zv9M|Geh5YcuG_(}r@Fto8mCywu;ZTgm3d|onkn`tbC_oAkrp0aLB#TP~lAk2-!>^-c2?6G;tZZ{OKBfe7t9 zV#IJLu-uW%;i*TgU@1p9XSW3Olq3+7xzMnNr-Y9sU6SsJ#A(?Xu3i*T#Z!a=ahBKbgT*8a%(UA4G--$_uOpZSEY-;a}|9nyy z#rnDSDaHXW(Vk4`J8!BUHdCG$t&vA$n>hxgQwm=;Uue_X@%R%Qk!o#qmC=JM+$I#D z+PZuF#HppCIhhO7Iq_b$5B=osHnlw5Wy#C&Cb8$e-tI@mkwP{ki}~h1*_G$Yf=f3g zyLJg&rqme#U3O@HVgJYzx=Rml4k7PL*wolIM5?lnpg>M}rwhAv=?GKkf&Bd=-cX(w zO|nqhwvYTomSs7YExHI`_J2A4~gIg4CVR z(RxLNIx(dUq-*M6;!Qr8Z*OrhuGCn&B{n-i-;f?GdL=S{qIJA1!JjTSV39tqFv>H|Y zJN1i;UiH=u1Z7)Vgcl|z*!Pp*@Fb-eFO-YD0|he>vtZvRMFiE= zvtb3s8b_PUtnHp!rglT4Q%=wAR zw?gGg#I{F7zH*bg2aFUJp%RhQ+Tjo!>Mly&$g((3z}dz7=m(|dm)6})ZF{mY`UBF? zc{g>!NVJ+~FDK*wuu#q>RzkLAjCC!L8WdKe@~h*N2SAhiypRkXecuAFhSmgjPE+*d zXSWD+#Rv5$udZDzU?-W?J%Q%MeoPEa@(#$}>=H5-UC?_?Aj<%pXh!cG>!qOKgzoO& zdOdDg--&Lxua)9NDuiaLeaSXSt6+Dgm%wzb6X8BxsVF~P<9b<-6622~yWE8JQ`Z$8 zK2^dS7?^43ivPz~iMgOptyYLr#M7fIg4G6g9_3Bs+)0R&tO+;{cun;&#a#U@xi38CSS`5I$lubPdOj3|p&`TC1l43{I;54FA}ru{rzv_frJ z6%(MqC3m-Hv><9X3IDTU_I&)!Z#pcg5{_CqDjEpYKnPBa(X#ufMA+f{Hxrb zd7$nn>IX~njsrs;E0O{$Vg@#+O26cs0a>!=|LnkHBMVNh#V%Y>@Jrb^2vVMQr;mL4 z0Id4ao`?I4@a_w#JiJ5nd|7yF6LxH1^hc}&?AQ8k4xBI*b84sBtduq)j4UK_1?LLt zgqQs&I*#ix-LS4?71ePNn_ID9J>Rkz7WyFynQ#;et`cxPvKY97sXo z3{aTW;eIw!$ym-iFf?4i?Hvf-9@ZHXDg&tt9XZX(u@DYb|NN&L8sBm<@{kWRmDeIH z*Ny~&zdR#UISR?^cM}K@*4++bgmfwrt7;cMwZA_huh%)e!-@5_2jrI>G|jqF&F4l zX~y|W9u57rvNfMjIw*Q6Jee3aTKF_}i5L z_qY$PXocou@X;2gGlQ7ME6uD&!GzPnAlGK#(-7Lx!^I)Tco&bY?=Lvmh?9!gc4=Wk z$vYYkQU8>f_;(hAO_w}udCBF1*EPibf3=-+r}A*&14(ppuu}q-7y;3O2RR)jr|~@R z!woi_O0mDbXO6VW_|NSK7H0g%62H}UzjKUu@-x4OOTT+Un$2Q3v;Vzqet1DE-YN{3 zU~lzl_2K9FP|n@|7--5m8}RN?$ts4$ zh{V-G#GU5IWxn|=l(BIT%WG-CMp(&fSaJ0`Q*h|MTV8}9nD*v~`HjQisUeQHj02Z| zD`g$d&Tkdk()g7R5GvRIsY@hyeQ}Ze7_IKj!rImr%8na4vAJu#Sz&L(uDK$v>tyJJ zzFN}+Me$*fUzAKLDFT;p&e$x_Dm0nF?KSExg`W?Bv}3{>KDcqQ9i=d)2-i!|;~F)-TjTEk`Tr2z7j2EC>i{!mkb-g^|K!@-z)>0r|1Glk~HGQkKHA#{GGQLq4cEfc3GW+ zq!E4&#=>qMfd)^IxI#_eBD_dnf6A{Lk(+A#T%0S;(praPhZI1P1eOQ5Ri3pmV+Mj$t-DfTG~6I2 z#3wy(X@$5Z^s`u{UhW)JoNB<&MX04=5n48fFg1;S}xE}B;5MC31V62p)A_Z~(R%cg?XOrYn5! zV=G$*wN9Q{mO&R03V0W2?$F{Nfsn@yu2Nx3v5AT03JQ4!l#?@aIlQ~8YBUFU|Pvffp zR>*Nu`Dr&RxlWJB8aytxtt_G-JEk93$9?&@6duN2rWv=sFCHQ4+j8g7%6>m4&sBT$ zeVk8p-d+~xYtnM7;^c@{eN2ia{fgX@5HnUZMF@Ak6H+%SLi3xK1FzLN)NOf8(*jO* zn-aMbH=MJFnP+$Np5;`8&pD$9W~F;~+nT`qWnk29MfhgKWE^BC znhgtjvz00)&yL}=-3ED#TAxcW$ZR8|Zpu8LE0%x}DM|M*2r@flmSF8@gEf<;d^gbfkvR+Y)gl=f?Fm ztu;rNYORdaNgqkhu|OOMDZ`_Vl?CZjT8;s7QQ?dMo?yd8JGYB+G^mMnXWI2D?5n&| zVv;%frLtDNWEN(s{>%v7ca4T$^ZRp|37&LL-(Y2lf(kW)Jg>`nXW@8JR#ZQb%)JCVK)zzsuVuD-D2h*0O!+t*6TPfyKgq8DU zpu++<#YOh{gy%CW`n8-3qlDSeC@DHH%)Hw1p$Vz$YfLabQ7q@?J!afa^Y3c}PkT{0 z(1k@RhIWpHxElmAAO?bLK9I3tcL;j#>t8B0v+-gRg%Y~u>0|1DRB8)-14S2j$HJ9{ zwgf%zRxi7=c)N7Nz2zgGvePw6&%BguQ!(pM`nOJvzohM&TAE%;b4obwv&u|-<8#{* zvSV%2SC{PPlc}~xB4aCZ@M-8={SgXoRHYX9An#wD6LTZbuMD_& z_s?<@=GEO^g9qn^cA1|Z>F>Amp150BtVGxr42`GY7VA5^!A{?~ywd$*O{zl1Il z{2G*4(#7{)E8T$D>c%MknYZgn@L5e0%ulW2pgYp&b8CKr7%XvX+cmkiMFqx6A zQR-P^^2Zm3YI8M-oF&oROG~&35g!&Rcek5DPWAzAZj0jaH>7VwPeXewG$yO>&lJUn zC^Hb7aS%F${oJ$R8sH1&jgEH_&(0Rs`ypFei!p)fWag0HLM4rxm9O#G&vOp|n;*m= zZ89rrzvf^I1_8APa6=e+*>KRSG>fNMn?oAz=PtfwCPL3;Iy2R$TIV`&Qw-pVp_h9r zh}Dt^|EC1nuK7H0+#v$n-LtmdjwLc(ajogYO1yn2dM8qkz-CN`Fe*}o5^pni6V2nG zT)kM>wjbfaaMN8@-~UA@R{B_gvgm?}l44Qa!VApqjQL;};JwE?levG?g!@6wqTQ%> z2-))k74F&s*zIXg<}ucf0myfsGwlG-g$%I2u`Xi|f%;DW4{eI|%mAt{}sHe6azO(1JC zZ2e2@H?C{SWStB*LW^s+atP3E0O^RE_gyM9bBQ*7yY$~e5>zVA-`YQH32LCOhwK%|iB&91Z2(s--QQY9?UfF6L zYFcWK(@|Fw5=(}lx<@~7-(A&Axsl?&4~7$?_pWV|6oJ<1*I&|~VfJ*jW}~Z_P+?CA zz#6kq++$>4iC{#KvpI>dz(pi3LQ6{{vh=_7(BtWL!*Z=A5ywh{3KSZXPWg*)G0@r= zF4wF5l(_kblSB%nN3j!XJg{H#SZ!@~9Nbjid~1wL553BS%Vhe%x~X@EnlGKyNy)$Y zOD^F}v~dJke;Pt0Zr9)HbK;F9SLEA7L#lH1V z=APaDpH(_EEGVvC)cHJ1V$;X%TMYl2ykBvo#6?|0BX%>BME?_;Z;Rf5cWbeqs?|Qt zdpv4aQ-%hgedUwGxy>O%4srJ+U-{dGz z-~8G2!}3~(lXK53mo;!uUYzll)3)D@sr^OBf@t8D*ZC~RiB}ztfxXa$|R$cbg+r=$SV@G24+czrtA|^(Q`>Iouj@8Aa-e&kxw0gH2 zFM}=Xw1h{C-pWWW+PvUvnDJW4tJ(IT9X*?0OeUMAJps11W=}CK3bD(Z z;>aAZtj%_E%8V=7)BA2HKlV0e_&Md;o3&dP1MBS$o~xO81vmQJrx=w@xyE#(YN26v z?}2k2b6&(PweIR$6%*t>b>qi&HlE*?@7;Uy=H_t61y@UI0hd<;J4K-FR(C&VRs7I;tSo1)bcL@>&!c^w^KJ7_mkK5`A7QD# z^?QveNAiT^`)$>dOAOksZQ#Gm`(?++9fFad{Z`A(-f1!>^&Rd19xdp(DYhwF!{x82`xhlIY>GHf=`;R=q zzT?V_|Mei-ab+|c%Z{r);P}Fmn=iSKUTS+;{NurUHihtl#kaP)&$eT$6f!9NQ8PK> zFw((48+pxlZn?83?y8UK_t#+}%KOi5Qd!n{z*j6k?~m_+KR4#9#ve#FYhZt}QugbW zW7?A|zs&`n`~%F8;$1Ut-e}LA?>K)KqrA^NmQ4Qg%Rg_Qx;5?9Je!VI{-k4OLJKQy zS2ozxs^Z#O~A-eYp1T z=Ho|htiat69>6hHoBhx0D-SK3B=zs?Yyqb*aA~j^xPsl%V!L_ku6iG(mI>^QP9ME* zp8p?GW;M6(_~TQh%uXDgko32G9&BaM&ve-G>=uDd4T!ZwP5=2-*X+%WdMZ{4Jj02> M)78&qol`;+0DQ!UrvLx| literal 0 HcmV?d00001 diff --git a/frameworks/MLflow/3.10.1/Dockerfile b/frameworks/MLflow/3.10.1/Dockerfile new file mode 100644 index 0000000..d997d51 --- /dev/null +++ b/frameworks/MLflow/3.10.1/Dockerfile @@ -0,0 +1,25 @@ +FROM opencloudos/opencloudos9-minimal:latest + +LABEL maintainer="stronking 363133710@qq.com" +LABEL org.opencontainers.image.source="https://gitee.com/OpenCloudOS/ai-agent-container" +LABEL org.opencontainers.image.description="MLflow 3.10.1 container image based on OpenCloudOS 9" + +ARG MLFLOW_VERSION=3.10.1 + +ENV LANG=en_US.UTF-8 +ENV LC_ALL=en_US.UTF-8 +ENV PYTHONUNBUFFERED=1 + +# Install MLflow +RUN python3 -m ensurepip +RUN --mount=type=cache,id=pip-cache-opencloudos9-cu128,target=/root/.cache/pip pip3 install mlflow==$MLFLOW_VERSION + +# Default MLflow configuration +ENV MLFLOW_HOST=0.0.0.0 +ENV MLFLOW_PORT=5000 + +EXPOSE 5000 + +WORKDIR /workspace + +CMD ["sh", "-c", "mlflow server --host ${MLFLOW_HOST} --port ${MLFLOW_PORT}"] diff --git a/frameworks/MLflow/3.10.1/README.md b/frameworks/MLflow/3.10.1/README.md new file mode 100644 index 0000000..f0711c8 --- /dev/null +++ b/frameworks/MLflow/3.10.1/README.md @@ -0,0 +1,189 @@ + +# MLflow on OpenCloudOS 9 + +## 基本信息 + +- **框架版本**:v3.10.1 +- **基础镜像**:opencloudos9-minimal +- **Python 版本**:3.11 +- **CUDA 版本**:N/A + +--- + +## 项目简介 + +[MLflow](https://github.com/mlflow/mlflow) 是一个开源的机器学习生命周期管理平台,主要提供以下能力: + +- 实验追踪(Experiment Tracking) +- 参数与指标记录 +- Artifact 管理 +- 模型注册(Model Registry) +- 模型部署(Serving) + +本镜像基于 OpenCloudOS 9 构建,提供轻量级 MLflow Tracking Server 运行环境。 + +--- + +## 构建 + +```bash +docker build -t oc9-mlflow:3.10.1 . +```` + +--- + +## 使用示例 + +### 查看 MLflow 版本 + +```bash +docker run --rm oc9-mlflow:3.10.1 \ + python3 -c "import mlflow; print(mlflow.__version__)" +``` + +--- + +## 启动 MLflow Tracking Server + +```bash +docker run -d \ + --name mlflow \ + -p 5000:5000 \ + oc9-mlflow:3.10.1 +``` + +访问: + +```text +http://localhost:5000 +``` + +--- + +## 持久化实验数据 + +默认情况下,容器中的实验数据会随着容器删除而丢失。 + +推荐挂载数据目录: + +```bash +docker run -d \ + --name mlflow \ + -p 5000:5000 \ + -v $(pwd)/mlruns:/mlruns \ + oc9-mlflow:3.10.1 \ + sh -c "mlflow server \ + --backend-store-uri sqlite:///mlruns/mlflow.db \ + --default-artifact-root /mlruns \ + --host 0.0.0.0 \ + --port 5000" +``` + +目录说明: + +```text +mlruns/ +├── mlflow.db +└── artifacts +``` + +--- + +## 实验追踪示例 + +创建示例脚本: + +```python +import mlflow +import random + +mlflow.set_tracking_uri("http://127.0.0.1:5000") +mlflow.set_experiment("demo-experiment") + +with mlflow.start_run(): + + mlflow.log_param("learning_rate", 0.01) + mlflow.log_param("epochs", 10) + + for step in range(10): + loss = 1.0 / (step + 1) + accuracy = 0.8 + random.random() * 0.1 + + mlflow.log_metric("loss", loss, step=step) + mlflow.log_metric("accuracy", accuracy, step=step) + + with open("result.txt", "w") as f: + f.write("training completed") + + mlflow.log_artifact("result.txt") +``` + +运行: + +```bash +python3 train.py +``` + +然后访问: + +```text +http://localhost:5000 +``` + +即可查看实验参数、指标和 Artifact。 + +--- + +## 容器网络使用示例 + +如果训练任务运行在其他容器中,建议使用 Docker Network。 + +创建网络: + +```bash +docker network create mlflow-net +``` + +启动 MLflow: + +```bash +docker run -d \ + --name mlflow \ + --network mlflow-net \ + -p 5000:5000 \ + oc9-mlflow:3.10.1 +``` + +训练容器中配置: + +```bash +export MLFLOW_TRACKING_URI=http://mlflow:5000 +``` + +--- + +## 默认配置 + +| 配置项 | 默认值 | +| ----------------- | ---------- | +| Host | 0.0.0.0 | +| Port | 5000 | +| Working Directory | /workspace | + +--- + +## 已知问题 + +* 当前镜像为轻量版,不包含 PyTorch、TensorFlow 等深度学习框架 +* 不包含 CUDA 与 GPU 运行环境 +* Model Serving 场景下,部分依赖需用户自行安装 + +--- + +## 上游项目 + +* MLflow: https://github.com/mlflow/mlflow +* OpenCloudOS: https://gitee.com/OpenCloudOS + +``` +``` diff --git a/frameworks/MLflow/3.10.1/build.conf b/frameworks/MLflow/3.10.1/build.conf new file mode 100644 index 0000000..baaea75 --- /dev/null +++ b/frameworks/MLflow/3.10.1/build.conf @@ -0,0 +1,4 @@ +# MLflow 3.10.1 on OpenCloudOS 9 +IMAGE_NAME=oc9-mlflow +IMAGE_TAG=3.10.1 +GPU_TEST=false \ No newline at end of file diff --git a/frameworks/MLflow/3.10.1/test.sh b/frameworks/MLflow/3.10.1/test.sh new file mode 100644 index 0000000..1cb9a5c --- /dev/null +++ b/frameworks/MLflow/3.10.1/test.sh @@ -0,0 +1,77 @@ +#!/bin/bash +set -e + +IMAGE="${1:?ERROR: 缺少镜像参数。用法: bash test.sh }" + +DOCKER_CMD="docker run --rm -e GIT_PYTHON_REFRESH=quiet" + +echo "=== MLflow 基础功能测试 ===" + +echo -n "检查 MLflow import 和版本... " +$DOCKER_CMD "$IMAGE" python3 -c "import mlflow; print(mlflow.__version__)" >/tmp/mlflow_import.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_import.log; exit 1; } + +echo -n "检查 MLflow CLI... " +$DOCKER_CMD "$IMAGE" mlflow --version >/tmp/mlflow_cli.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_cli.log; exit 1; } + +echo -n "检查实验追踪核心功能... " +$DOCKER_CMD "$IMAGE" python3 -c " +import os +import tempfile +import mlflow + +tmpdir = tempfile.mkdtemp() +db_path = os.path.join(tmpdir, 'mlflow.db') + +mlflow.set_tracking_uri('sqlite:///' + db_path) +mlflow.set_experiment('ci-test-experiment') + +with mlflow.start_run(): + mlflow.log_param('learning_rate', 0.01) + mlflow.log_metric('accuracy', 0.95) + + run = mlflow.active_run() + assert run is not None + assert run.info.run_id is not None + +print('MLflow experiment tracking works') +" >/tmp/mlflow_tracking.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_tracking.log; exit 1; } + +echo -n "检查 MLflow Tracking Server 启动... " +$DOCKER_CMD "$IMAGE" bash -c " +set -e + +TMPDIR=\$(mktemp -d) + +mlflow server \ + --backend-store-uri sqlite:///\$TMPDIR/mlflow.db \ + --default-artifact-root \$TMPDIR/artifacts \ + --host 127.0.0.1 \ + --port 5000 >/tmp/mlflow_server.log 2>&1 & + +PID=\$! + +for i in \$(seq 1 60); do + if curl -fs http://127.0.0.1:5000/health >/dev/null 2>&1; then + kill \$PID + wait \$PID 2>/dev/null || true + exit 0 + fi + + if ! kill -0 \$PID 2>/dev/null; then + cat /tmp/mlflow_server.log + exit 1 + fi + + sleep 1 +done + +cat /tmp/mlflow_server.log +kill \$PID 2>/dev/null || true +exit 1 +" >/tmp/mlflow_server_check.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_server_check.log; exit 1; } + +echo "=== 所有测试通过 ===" \ No newline at end of file diff --git a/frameworks/MLflow/3.10.1/test_result.png b/frameworks/MLflow/3.10.1/test_result.png new file mode 100644 index 0000000000000000000000000000000000000000..a5605dbb07711f3a7fc4d1fd311ef03a7dac8c26 GIT binary patch literal 18925 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
  • 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/tmp/mlflow_import.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_import.log; exit 1; } + +echo -n "检查 MLflow CLI... " +$DOCKER_CMD "$IMAGE" mlflow --version >/tmp/mlflow_cli.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_cli.log; exit 1; } + +echo -n "检查实验追踪核心功能... " +$DOCKER_CMD "$IMAGE" python3 -c " +import os +import tempfile +import mlflow + +tmpdir = tempfile.mkdtemp() +db_path = os.path.join(tmpdir, 'mlflow.db') + +mlflow.set_tracking_uri('sqlite:///' + db_path) +mlflow.set_experiment('ci-test-experiment') + +with mlflow.start_run(): + mlflow.log_param('learning_rate', 0.01) + mlflow.log_metric('accuracy', 0.95) + + run = mlflow.active_run() + assert run is not None + assert run.info.run_id is not None + +print('MLflow experiment tracking works') +" >/tmp/mlflow_tracking.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_tracking.log; exit 1; } + +echo -n "检查 MLflow Tracking Server 启动... " +$DOCKER_CMD "$IMAGE" bash -c " +set -e + +TMPDIR=\$(mktemp -d) + +mlflow server \ + --backend-store-uri sqlite:///\$TMPDIR/mlflow.db \ + --default-artifact-root \$TMPDIR/artifacts \ + --host 127.0.0.1 \ + --port 5000 >/tmp/mlflow_server.log 2>&1 & + +PID=\$! + +for i in \$(seq 1 60); do + if curl -fs http://127.0.0.1:5000/health >/dev/null 2>&1; then + kill \$PID + wait \$PID 2>/dev/null || true + exit 0 + fi + + if ! kill -0 \$PID 2>/dev/null; then + cat /tmp/mlflow_server.log + exit 1 + fi + + sleep 1 +done + +cat /tmp/mlflow_server.log +kill \$PID 2>/dev/null || true +exit 1 +" >/tmp/mlflow_server_check.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_server_check.log; exit 1; } + +echo "=== 所有测试通过 ===" \ No newline at end of file diff --git a/frameworks/MLflow/3.11.0/test_result.png b/frameworks/MLflow/3.11.0/test_result.png new file mode 100644 index 0000000000000000000000000000000000000000..f4e0160ef3a7bd89aad4268fcb4aaef32731592c GIT binary patch literal 18850 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 literal 0 HcmV?d00001 diff --git a/frameworks/MLflow/3.9.0/Dockerfile b/frameworks/MLflow/3.9.0/Dockerfile new file mode 100644 index 0000000..e565b30 --- /dev/null +++ b/frameworks/MLflow/3.9.0/Dockerfile @@ -0,0 +1,26 @@ +FROM opencloudos/opencloudos9-minimal:latest + +LABEL maintainer="stronking 363133710@qq.com" +LABEL org.opencontainers.image.source="https://gitee.com/OpenCloudOS/ai-agent-container" +LABEL org.opencontainers.image.description="MLflow 3.9.0 container image based on OpenCloudOS 9" + +ARG MLFLOW_VERSION=3.9.0 + +ENV LANG=en_US.UTF-8 +ENV LC_ALL=en_US.UTF-8 +ENV PYTHONUNBUFFERED=1 + +# Install MLflow +RUN python3 -m ensurepip +RUN --mount=type=cache,id=pip-cache-opencloudos9-cu128,target=/root/.cache/pip pip3 install mlflow==$MLFLOW_VERSION + +# Default MLflow configuration +ENV MLFLOW_HOST=0.0.0.0 +ENV MLFLOW_PORT=5000 + +EXPOSE 5000 + +WORKDIR /workspace + +CMD ["sh", "-c", "mlflow server --host ${MLFLOW_HOST} --port ${MLFLOW_PORT}"] + diff --git a/frameworks/MLflow/3.9.0/README.md b/frameworks/MLflow/3.9.0/README.md new file mode 100644 index 0000000..54f8d72 --- /dev/null +++ b/frameworks/MLflow/3.9.0/README.md @@ -0,0 +1,189 @@ + +# MLflow on OpenCloudOS 9 + +## 基本信息 + +- **框架版本**:v3.9.0 +- **基础镜像**:opencloudos9-minimal +- **Python 版本**:3.11 +- **CUDA 版本**:N/A + +--- + +## 项目简介 + +[MLflow](https://github.com/mlflow/mlflow) 是一个开源的机器学习生命周期管理平台,主要提供以下能力: + +- 实验追踪(Experiment Tracking) +- 参数与指标记录 +- Artifact 管理 +- 模型注册(Model Registry) +- 模型部署(Serving) + +本镜像基于 OpenCloudOS 9 构建,提供轻量级 MLflow Tracking Server 运行环境。 + +--- + +## 构建 + +```bash +docker build -t oc9-mlflow:3.9.0 . +```` + +--- + +## 使用示例 + +### 查看 MLflow 版本 + +```bash +docker run --rm oc9-mlflow:3.9.0 \ + python3 -c "import mlflow; print(mlflow.__version__)" +``` + +--- + +## 启动 MLflow Tracking Server + +```bash +docker run -d \ + --name mlflow \ + -p 5000:5000 \ + oc9-mlflow:3.9.0 +``` + +访问: + +```text +http://localhost:5000 +``` + +--- + +## 持久化实验数据 + +默认情况下,容器中的实验数据会随着容器删除而丢失。 + +推荐挂载数据目录: + +```bash +docker run -d \ + --name mlflow \ + -p 5000:5000 \ + -v $(pwd)/mlruns:/mlruns \ + oc9-mlflow:3.9.0 \ + sh -c "mlflow server \ + --backend-store-uri sqlite:///mlruns/mlflow.db \ + --default-artifact-root /mlruns \ + --host 0.0.0.0 \ + --port 5000" +``` + +目录说明: + +```text +mlruns/ +├── mlflow.db +└── artifacts +``` + +--- + +## 实验追踪示例 + +创建示例脚本: + +```python +import mlflow +import random + +mlflow.set_tracking_uri("http://127.0.0.1:5000") +mlflow.set_experiment("demo-experiment") + +with mlflow.start_run(): + + mlflow.log_param("learning_rate", 0.01) + mlflow.log_param("epochs", 10) + + for step in range(10): + loss = 1.0 / (step + 1) + accuracy = 0.8 + random.random() * 0.1 + + mlflow.log_metric("loss", loss, step=step) + mlflow.log_metric("accuracy", accuracy, step=step) + + with open("result.txt", "w") as f: + f.write("training completed") + + mlflow.log_artifact("result.txt") +``` + +运行: + +```bash +python3 train.py +``` + +然后访问: + +```text +http://localhost:5000 +``` + +即可查看实验参数、指标和 Artifact。 + +--- + +## 容器网络使用示例 + +如果训练任务运行在其他容器中,建议使用 Docker Network。 + +创建网络: + +```bash +docker network create mlflow-net +``` + +启动 MLflow: + +```bash +docker run -d \ + --name mlflow \ + --network mlflow-net \ + -p 5000:5000 \ + oc9-mlflow:3.9.0 +``` + +训练容器中配置: + +```bash +export MLFLOW_TRACKING_URI=http://mlflow:5000 +``` + +--- + +## 默认配置 + +| 配置项 | 默认值 | +| ----------------- | ---------- | +| Host | 0.0.0.0 | +| Port | 5000 | +| Working Directory | /workspace | + +--- + +## 已知问题 + +* 当前镜像为轻量版,不包含 PyTorch、TensorFlow 等深度学习框架 +* 不包含 CUDA 与 GPU 运行环境 +* Model Serving 场景下,部分依赖需用户自行安装 + +--- + +## 上游项目 + +* MLflow: https://github.com/mlflow/mlflow +* OpenCloudOS: https://gitee.com/OpenCloudOS + +``` +``` diff --git a/frameworks/MLflow/3.9.0/build.conf b/frameworks/MLflow/3.9.0/build.conf new file mode 100644 index 0000000..e937903 --- /dev/null +++ b/frameworks/MLflow/3.9.0/build.conf @@ -0,0 +1,4 @@ +# MLflow 3.9.0 on OpenCloudOS 9 +IMAGE_NAME=oc9-mlflow +IMAGE_TAG=3.9.0 +GPU_TEST=false \ No newline at end of file diff --git a/frameworks/MLflow/3.9.0/test.sh b/frameworks/MLflow/3.9.0/test.sh new file mode 100644 index 0000000..1cb9a5c --- /dev/null +++ b/frameworks/MLflow/3.9.0/test.sh @@ -0,0 +1,77 @@ +#!/bin/bash +set -e + +IMAGE="${1:?ERROR: 缺少镜像参数。用法: bash test.sh }" + +DOCKER_CMD="docker run --rm -e GIT_PYTHON_REFRESH=quiet" + +echo "=== MLflow 基础功能测试 ===" + +echo -n "检查 MLflow import 和版本... " +$DOCKER_CMD "$IMAGE" python3 -c "import mlflow; print(mlflow.__version__)" >/tmp/mlflow_import.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_import.log; exit 1; } + +echo -n "检查 MLflow CLI... " +$DOCKER_CMD "$IMAGE" mlflow --version >/tmp/mlflow_cli.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_cli.log; exit 1; } + +echo -n "检查实验追踪核心功能... " +$DOCKER_CMD "$IMAGE" python3 -c " +import os +import tempfile +import mlflow + +tmpdir = tempfile.mkdtemp() +db_path = os.path.join(tmpdir, 'mlflow.db') + +mlflow.set_tracking_uri('sqlite:///' + db_path) +mlflow.set_experiment('ci-test-experiment') + +with mlflow.start_run(): + mlflow.log_param('learning_rate', 0.01) + mlflow.log_metric('accuracy', 0.95) + + run = mlflow.active_run() + assert run is not None + assert run.info.run_id is not None + +print('MLflow experiment tracking works') +" >/tmp/mlflow_tracking.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_tracking.log; exit 1; } + +echo -n "检查 MLflow Tracking Server 启动... " +$DOCKER_CMD "$IMAGE" bash -c " +set -e + +TMPDIR=\$(mktemp -d) + +mlflow server \ + --backend-store-uri sqlite:///\$TMPDIR/mlflow.db \ + --default-artifact-root \$TMPDIR/artifacts \ + --host 127.0.0.1 \ + --port 5000 >/tmp/mlflow_server.log 2>&1 & + +PID=\$! + +for i in \$(seq 1 60); do + if curl -fs http://127.0.0.1:5000/health >/dev/null 2>&1; then + kill \$PID + wait \$PID 2>/dev/null || true + exit 0 + fi + + if ! kill -0 \$PID 2>/dev/null; then + cat /tmp/mlflow_server.log + exit 1 + fi + + sleep 1 +done + +cat /tmp/mlflow_server.log +kill \$PID 2>/dev/null || true +exit 1 +" >/tmp/mlflow_server_check.log 2>&1 \ + && echo "✓ 通过" || { echo "✗ 失败"; cat /tmp/mlflow_server_check.log; exit 1; } + +echo "=== 所有测试通过 ===" \ No newline at end of file diff --git a/frameworks/MLflow/3.9.0/test_result.png b/frameworks/MLflow/3.9.0/test_result.png new file mode 100644 index 0000000000000000000000000000000000000000..6973a5815d3c46ba3723cc4535eec2c7049ba715 GIT binary patch literal 18702 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 literal 0 HcmV?d00001 -- Gitee