ModelArts 自定义镜像部署避坑指南:8080 端口、/home/mind/model 与 ma-user
写在前面
用 ModelArts 的预置引擎部署模型,基本是点几下的事;一旦换成自定义镜像,第一次部署大概率会卡在"服务一直部署中"或者"调用返回 502"。这篇把自己踩过的几个坑按顺序整理一遍,给同样在折腾自定义镜像的同学省点时间。
一、先搞清楚平台对镜像的三条硬约束
自定义镜像不是"能跑就行",ModelArts 对镜像有明确规范,这三条不满足必然失败:
1. 必须内置 ma-user 用户,uid=1000、gid=100
平台会以 uid=1000 的身份启动容器,镜像里没有这个用户,容器起来就挂。Dockerfile 里加这两行:
RUN groupadd -g 100 ma-group && \
useradd -d /home/ma-user -m -u 1000 -g 100 -s /bin/bash ma-user
USER 1000
2. 推理服务必须监听 8080 端口
平台只把容器 8080 端口的服务注册到 API 网关,写 app.run(port=5000) 之类的一律访问不到。协议按镜像实际情况填,HTTP/HTTPS 都支持。
3. 模型包目录名必须叫 model,落到容器里是 /home/mind/model
OBS 上的模型目录下载到容器后固定挂载在 /home/mind/model,且文件 owner 会被统一改成 ma-user。所以推理脚本里读模型要用这个绝对路径或者相对脚本自身的路径,千万别写死本地的 ./weights——本地跑得好好的,上云就找不到文件。
顺便提一个容易忽略的点:代码里不要对 /home/mind/model 做写操作,该目录在线上是可写的但权限收紧过,只读推理才是稳妥做法。
二、懒人版最小流程
- 本地按上面三条改好镜像,推到 SWR;
- 本地先验证一遍,避免上云才发现问题:
docker run --user 1000:100 -p 8080:8080 -v $(pwd)/model:/home/mind/model custom_engine:v1
curl http://127.0.0.1:8080/health
- OBS 里建一个目录(名字就叫
model),把权重、推理脚本、配置文件传上去; - ModelArts 控制台 → 模型管理 → 创建模型:元模型来源选"从对象存储服务(OBS)中选择",AI 引擎选 Custom,再选 SWR 镜像;
- 模型状态"正常"后 → 部署 → 在线服务,选实例规格,等状态变"运行中"。
注意第一步本地验证只能验证个大概:-v 挂载进去的目录是 root 权限,和线上 ma-user 的权限模型不完全一致,所以权限相关的问题还得靠线上日志判断。
三、调用环节
服务跑起来之后,服务详情页会给一个 API 接口地址(形如 https://xxx/v1/infers/{service_id},以控制台实际展示为准)。请求头里要带 IAM token:
import requests
def get_token(user, password, domain, project_id, region="cn-north-4"):
body = {
"auth": {
"identity": {
"methods": ["password"],
"password": {"user": {"name": user, "password": password, "domain": {"name": domain}}}
},
"scope": {"project": {"id": project_id}}
}
}
r = requests.post(f"https://iam.{region}.myhuaweicloud.com/v3/auth/tokens",
json=body, verify=False)
return r.headers["X-Subject-Token"]
token = get_token("你的用户名", "你的密码", "你的账号名", "项目ID")
resp = requests.post(SERVICE_URL,
headers={"X-Auth-Token": token, "Content-Type": "application/json"},
json={"data": "your input"})
print(resp.status_code, resp.text)
token 有效期 24 小时,长期跑的服务记得做缓存或提前刷新,别每次请求都去换。
四、最常踩的五个坑
| 现象 | 常见原因 | 处理 |
|---|---|---|
| 服务一直"部署中",最后失败 | 镜像架构和资源池不一致(x86 拉 AMD64、ARM 拉了 x86) | docker build --platform linux/amd64 重新构建 |
| 服务"运行中"但调用 502 | 服务没监听 8080,或监听在 127.0.0.1 上 | 绑 0.0.0.0:8080 |
| 容器启动即退出 | 没有 ma-user / 启动命令在前台没挂住 | 加 USER 1000,CMD 用前台进程 |
| 推理报"找不到模型文件" | 路径写死成本地相对路径 | 统一用 /home/mind/model |
| 健康检查一直不通过 | 没实现 /health,或返回码不是 200 |
加一个直接 return 200 的 /health |
排查顺序建议:先看服务详情页的事件,再看日志。事件里通常会直接写"镜像拉取失败""健康检查超时",比翻日志快得多。
五、两件小事
- 用完记得停。在线服务按实例时长计费,调试阶段建议实例数 1、用完就停,别留一堆"运行中"的实例过夜。
- 别把 AK/SK 写进镜像。镜像推到 SWR 是可被拉取的,凭据一律走环境变量或委托(Agency)授权。
自定义镜像这条路前期确实比预置引擎麻烦,但把上面三条规范和五个坑过一遍,后面基本就是改模型换镜像的重复劳动了。祝部署顺利。
- 点赞
- 收藏
- 关注作者
评论(0)