记一次模型服务Docker容器化的经历

今天本来只想干一件事:把我的一些本地模型服务做成 Docker 容器,方便后续迁移。
结果真动手之后,才发现这事没想象中那么顺。

我的环境本身就比较复杂:在已经虚拟化的 Ubuntu 系统里又装了 vGPU 驱动。
没容器化之前,服务靠一堆本地依赖勉强维持,尤其是 CUDA 相关版本兼容,环境非常脆弱。
很多时候只要某个依赖被动过一点,模型服务就可能直接起不来。
也正因为这样,才有了这次“必须容器化”的经历。

先说结果

这次改造最直接的好处,不是“跑起来了”这么简单,而是把原来松散、脆弱、难迁移的运行环境,整理成了一套可复用、可打包、可迁移的方案。

另外,镜像体积降下来以后,构建和推送都稳了不少,失败重试的情况也少了很多。

这次主要踩了哪些坑

一开始我以为主要问题会出在容器编排,结果真正花时间的是四件事:

  1. 构建内容太大
    一些不该进镜像的大文件被带进去了,导致镜像层太大,推送压力一下子变重。

  2. GPU 运行环境太敏感
    vGPU、CUDA、推理运行时之间版本关系很挑,稍微不合适,就会在运行阶段出问题。

  3. 超时参数看着配了,但实际没按预期生效
    特别是带 sudo 的执行方式,环境变量继承经常和想的不一样,排查时很容易被带偏。

  4. docker push 一直 retry,问题不在本地客户端
    当时 push 过程反复重试,我先后查了本地环境、网关和 Nexus 服务。
    最后定位到网关缓存空间被占满,导致上传过程异常。
    处理方式是:网关对 Docker 仓库推送这条路径不做缓存,问题随即消失。

后来是怎么理顺的

真正有效的做法,是不再只盯某条命令对不对,而是把问题分开处理:

  • 先把构建内容里不需要的东西排出去,减小镜像层
  • 再把 GPU 依赖版本固定住,尽量不要来回变
  • 推送失败时,客户端参数和服务端上传问题分开看

这样以后,很多以前混在一起的问题都能看清楚,不会一上来就全盘怀疑。

这次做完之后,留下了什么

这轮工作最有价值的地方,不是一次过关,而是留下了后面还能继续用的经验:

  • 一套更轻量的镜像做法
  • 一组更稳的 GPU 运行环境组合
  • 一种更清楚的排查顺序(构建、运行、推送分开处理)

后面准备怎么做

接下来我会坚持几件事:

  • 默认优先用瘦身后的镜像方案
  • 控制单层大小,尽量避免超大层带来的上传不稳
  • 再遇到推送异常,第一时间看上传相关日志,不只盯客户端

这次最大的收获,是把“能跑”变成了“能迁移、能复用、出问题也知道怎么查”。
对模型服务这种依赖敏感的场景来说,容器化不只是方便部署,更是为了把风险控制在自己能处理的范围里。

build with Hugo, theme Stack, visits 0