1、LabelStudio部署
● 1、具体部署步骤:
bash
mkdir -p ~/label-studio-data
# 运行 Label Studio 容器
docker run -d \
--name label-studio \
-p 8088:8080 \
-v ~/label-studio-data:/label-studio/data \
--restart always \
heartexlabs/label-studio:latest
● 2、部署参数详解:
| 参数 | 说明 | 作用 |
|---|---|---|
| -d | detached mode | 后台运行容器 |
| --name | label-studio | 容器名称 便于管理和识别 |
| -p | 8088:8080 | 端口映射 宿主机 8088 → 容器 8080 |
| -v | ~/label-studio-data:/label-studio/data | 数据卷挂载 持久化标注数据 |
| --restart | always | 重启策略 服务器重启后自动启动 |
● 3、端口映射原理:
外部访问 宿主机 Docker 容器 http://192.168.3.222:8088 → 宿主机 8088 端口 → 容器 8080 端口 ↓ ↓ Docker 网络映射 Label Studio 服务
2、home.py的修改
● 1、文件路径:
/home/myapp/myapp/views/home.py
● 2、 配置修改:
bash
#-----------------原始配置---------------------
{
"name": 'label_platform',
"title": __('标注平台'),
"icon": '<svg t="1658320508784" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3263" width="200" height="200"><path d="M875.65 912h-380a36 36 0 0 1 0-72h380a36 36 0 1 1 0 72zM812.26 284.82L285.39 811.69l-88.11 15.1L212 738l526.72-526.72 73.54 73.54m90.51-11.31L750 120.77a16 16 0 0 0-22.62 0L152.5 695.68a34.11 34.11 0 0 0-9.5 18.56l-25.95 156.23a32 32 0 0 0 37 36.78l155.38-26.62a34.2 34.2 0 0 0 18.38-9.52l575-575a16 16 0 0 0 0-22.63z" p-id="3264"></path></svg>',
"menu_type": "api", # ← 错误:内部 API 类型
"disable": True, # ← 错误:菜单被禁用
"url": "/metadata_table_modelview/api/" # ← 错误:内部 API 路径
}
#----------------现在的配置--------------------
{
"name": 'label_platform',
"title": __('标注平台'),
"icon": '<svg t="1658320508784" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3263" width="200" height="200"><path d="M875.65 912h-380a36 36 0 0 1 0-72h380a36 36 0 1 1 0 72zM812.26 284.82L285.39 811.69l-88.11 15.1L212 738l526.72-526.72 73.54 73.54m90.51-11.31L750 120.77a16 16 0 0 0-22.62 0L152.5 695.68a34.11 34.11 0 0 0-9.5 18.56l-25.95 156.23a32 32 0 0 0 37 36.78l155.38-26.62a34.2 34.2 0 0 0 18.38-9.52l575-575a16 16 0 0 0 0-22.63z" p-id="3264"></path></svg>',
"menu_type": "out_link", # ✅ 修改为外部链接类型
"disable": False, # ✅ 启用菜单
"url": "http://192.168.3.222:8088" # ✅ 指向 Label Studio 地址
}
● 3、网络链接原理:
┌─────────────────┐
│ 用户浏览器 │
│ 访问 Cube Studio│
└────────┬────────┘
│ 1. 点击"标注平台"菜单
↓
┌─────────────────┐
│ Cube Studio │
│ 返回跳转链接 │
│ http://192... │
└────────┬────────┘
│ 2. 浏览器跳转到新地址
↓
┌─────────────────┐
│ Label Studio │
│ 192.168.3.222 │
│ 端口 8088 │
└─────────────────┘
- 关键点:
- 网络可达性:Cube Studio 和 Label Studio 在同一网络(或可路由的网络)
- 端口映射:Docker 的 -p 8088:8080 让外部可以访问
- URL 配置:menu_type: "out_link" 让浏览器直接跳转,而不是在 Cube Studio 内部请求
3、ConfigMap持久化配置
3.1 为什么要使用ConfigMap?
● 1、 Docker镜像的不可变性
Docker 镜像 = 只读的文件系统层
├── 基础操作系统层
├── Python 环境层
├── Cube Studio 代码层 ← home.py 在这里
└── 配置文件层
- Docker 镜像一旦构建完成,内部的文件就固定了
- 每个镜像有唯一的 ID,比如 ccr.ccs.tencentyun.com/cube-studio/kubeflow-dashboard:2025.03.01
- 这个镜像里的 home.py 永远是构建时的版本
● 2、镜像容器
Docker 容器 = 镜像 + 可写层
├── 只读镜像层(不可改)
└── 临时可写层 ← 你在这里修改文件
kubectl exec -it pod-name -- vi /home/myapp/myapp/views/home.py
实际上是在临时可写层修改文件,这一层的数据:
● ❌ 不会保存回镜像
● ❌ Pod 重启后会被清空
● ❌ 每次 Pod 启动都从干净的镜像开始
这就像在沙滩上写字,海水一来(Pod 重启)字就消失了。
● 3、🎯 解决方案的原理:ConfigMap--Kubernetes 的配置存储
ConfigMap = 键值对存储
├── Key: home.py
└── Value: <完整的文件内容>
ConfigMap 存储在哪里?
- 存储在 Kubernetes 的 etcd 数据库中
- 与 Pod 生命周期无关
- 持久化存储,不会因为 Pod 重启而消失
bash
# 🏗️ 传统方式(会丢失配置)
┌─────────────────┐
│ Docker 镜像 │
│ ├── home.py │ ← 固定内容
│ └── ... │
└─────────────────┘
↓
┌─────────────────┐
│ 运行的 Pod │
│ ├── home.py │ ← 你修改了这里
│ └── ... │
└─────────────────┘
↓ 重启
┌─────────────────┐
│ 新的 Pod │
│ ├── home.py │ ← 又变回原样!
│ └── ... │
└─────────────────┘
# ✅ ConfigMap 挂载方式(配置持久化)
┌─────────────────┐ ┌──────────────┐
│ Docker 镜像 │ │ ConfigMap │
│ ├── home.py │ │ home.py: │
│ └── ... │ │ <新内容> │
└─────────────────┘ └──────────────┘
↓ ↓
┌─────────────────────────────────────┐
│ 运行的 Pod │
│ ├── 镜像中的文件 │
│ └── /home/myapp/myapp/views/ │
│ └── home.py ← 挂载自 ConfigMap │
└─────────────────────────────────────┘
↓ 重启
┌─────────────────────────────────────┐
│ 新的 Pod │
│ ├── 镜像中的文件 │
│ └── /home/myapp/myapp/views/ │
│ └── home.py ← 还是来自 ConfigMap│
└─────────────────────────────────────┘
3.2 具体步骤
● 1、导出并修改配置文件
bash
# 1. 导出当前的 home.py 文件
kubectl exec -it kubeflow-dashboard-5f8465f85f-lf4sg -n infra -- cat /home/myapp/myapp/views/home.py > /tmp/home.py
# 2. 备份原文件
cp /tmp/home.py /tmp/home.py.backup
# 3. 编辑文件
nano /tmp/home.py
在nano编辑器中,找到配置字段,修改为:
{
"name": 'label_platform',
"title": __('标注平台'),
"icon": '<svg t="1658320508784" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3263" width="200" height="200"><path d="M875.65 912h-380a36 36 0 0 1 0-72h380a36 36 0 1 1 0 72zM812.26 284.82L285.39 811.69l-88.11 15.1L212 738l526.72-526.72 73.54 73.54m90.51-11.31L750 120.77a16 16 0 0 0-22.62 0L152.5 695.68a34.11 34.11 0 0 0-9.5 18.56l-25.95 156.23a32 32 0 0 0 37 36.78l155.38-26.62a34.2 34.2 0 0 0 18.38-9.52l575-575a16 16 0 0 0 0-22.63z" p-id="3264"></path></svg>',
"menu_type": "out_link",
"disable": False,
"url": "http://192.168.3.222:8088"
}
⚠️ 注意三个关键点:
● "menu_type": "out_link"(不是 "api")
● "disable": False(不要注释掉)
● "url": "http://192.168.3.222:8088"(用服务器 IP,不是 localhost)
● 2、创建或更新ConfigMap
bash
# 删除旧的 ConfigMap(如果存在)
kubectl delete configmap home-config -n infra 2>/dev/null
# 创建新的 ConfigMap
kubectl create configmap home-config --from-file=home.py=/tmp/home.py -n infra
# 验证 ConfigMap 创建成功
kubectl get configmap home-config -n infra
● 3、获取当前Deployment配置
bash
# 导出当前配置
kubectl get deployment kubeflow-dashboard -n infra -o yaml > /tmp/deployment-original.yaml
● 4、创建修改后的Deployment配置
bash
# 创建修改脚本
cat > /tmp/add-configmap.sh << 'EOF'
#!/bin/bash
# 读取原始配置
kubectl get deployment kubeflow-dashboard -n infra -o yaml > /tmp/deployment-new.yaml
# 使用 Python 脚本来正确添加配置
python3 << 'PYTHON_EOF'
import yaml
# 读取 YAML
with open('/tmp/deployment-new.yaml', 'r') as f:
deployment = yaml.safe_load(f)
# 找到 containers
containers = deployment['spec']['template']['spec']['containers']
main_container = None
for i, container in enumerate(containers):
if container['name'] == 'kubeflow-dashboard':
main_container = container
container_index = i
break
if not main_container:
print("找不到 kubeflow-dashboard 容器")
exit(1)
# 添加 volumeMount
if 'volumeMounts' not in main_container:
main_container['volumeMounts'] = []
# 检查是否已存在,避免重复添加
home_config_exists = any(vm.get('name') == 'home-config' for vm in main_container['volumeMounts'])
if not home_config_exists:
main_container['volumeMounts'].append({
'name': 'home-config',
'mountPath': '/home/myapp/myapp/views/home.py',
'subPath': 'home.py'
})
# 添加 volume
if 'volumes' not in deployment['spec']['template']['spec']:
deployment['spec']['template']['spec']['volumes'] = []
volumes = deployment['spec']['template']['spec']['volumes']
volume_exists = any(v.get('name') == 'home-config' for v in volumes)
if not volume_exists:
volumes.append({
'name': 'home-config',
'configMap': {
'name': 'home-config'
}
})
# 保存
with open('/tmp/deployment-new.yaml', 'w') as f:
yaml.dump(deployment, f, default_flow_style=False)
print("配置文件已修改完成")
PYTHON_EOF
echo "配置修改完成!"
EOF
# 给脚本添加执行权限
chmod +x /tmp/add-configmap.sh
# 执行脚本
/tmp/add-configmap.sh
● 5、应用新配置
bash
# 应用修改后的配置
kubectl apply -f /tmp/deployment-new.yaml
# 观察 Pod 重启过程
kubectl get pods -n infra -w
● 6、验证是否生效
bash
等待新 Pod 完全启动
sleep 30
# 获取新 Pod 名称
NEW_POD=$(kubectl get pod -n infra | grep kubeflow-dashboard | grep Running | grep "1/1" | head -n 1 | awk '{print $1}')
echo "新 Pod 名称: $NEW_POD"
# 检查配置文件是否正确挂载
kubectl exec -it $NEW_POD -n infra -- cat /home/myapp/myapp/views/home.py | grep -A 7 "label_platform"
然后刷新浏览器即可看到
3.3 技术细节解析



4、结果


如图,点击标注平台会跳转至labelstudio中