1、对python服务进行打包编写DockerFile# 私有化 AI Infra 引擎 v2 — 联调(.249 bigDataServer)与线上(.42/.43/.44)**同一镜像**, # 运行时 -e APP_ENVtest|prod 选烧进镜像的双档配置 (二文件合并案 DEPLOY §2 手术件4)。 # base 锁 bullseye (glibc 2.31): CentOS7 kernel 3.10seccomp 拦 glibc2.34 的 clone3 → pthread EPERM # (DEPLOY §5 头号坑, 两台宿主均 CentOS7; 万一必须升 base, 退路 --security-opt seccompunconfined) # docker.io 海外直连慢/不稳 (10-20 .249 实测拉取 4 分钟): 从零构建的机器可换国内前缀 # FROM docker.m.daocloud.io/library/python:3.11-slim-bullseye — 同一枚镜像走 DaoCloud 公共代理 FROM python:3.11-slim-bullseye ENV PYTHONUNBUFFERED1 \ PIP_NO_CACHE_DIR1 \ PYTHONUTF81 \ TZAsia/Shanghai \ APP_ENVtest # 10-20 D4 两级实测, apt 层整体绕掉: ①.249 出口到 deb.debian.org(Fastly 境外)80 不通; # ②换阿里云后索引通但 bullseye-security 文件 404 (Debian11 已 2026-08 停止常规支持, 镜像池清空索引滞后)。 # 原 apt 只为装 curl(HEALTHCHECK 用)tzdata(base 镜像 python:3.11-slim 自带): # curl → 健康检查改 python urllib (镜像内必有); tzdata → 仅剩时区软链, ln 即可 RUN ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime WORKDIR /app COPY requirements.txt . # torch 先走 CPU 专用索引: PyPI 默认轮CUDA 捆绑 (5GB, 破 全量 2~3GB 打包结论); # 装得 2.13.0cpu 后, 后续 requirements 的 torch2.13.0 按 PEP440 视为已满足不再回拉 # 10-20 用户口径「海外源大概率不通, 尽量国内」: torch 轮走上交大 pytorch-wheels 镜像 # (备选 南大 https://mirror.nju.edu.cn/pytorch-wheels/cpu); pypi 走阿里云; # 国内镜像若同步滞后缺 2.13.0 版本 → 回退官方 https://download.pytorch.org/whl/cpu (443 实测可达) RUN pip install --index-url https://mirror.sjtu.edu.cn/pytorch-wheels/cpu torch2.13.0 \ pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ COPY . . EXPOSE 10021 # 健康检查不依赖 curl (apt 层已绕掉, 见上): 用镜像内 python 打 /health, 200healthy HEALTHCHECK --interval30s --timeout5s --start-period120s \ CMD python -c import urllib.request,sys; sys.exit(0 if urllib.request.urlopen(http://127.0.0.1:10021/health,timeout4).getcode()200 else 1) # SERVER_HOST/PORT(10021) 由 config 读 .env.{APP_ENV}; Linux 默认可用 proactor-free 循环, # run.py 的 Selector 策略仅 win32 生效 — 容器内与开发机同一条启动入口 CMD [python, run.py]Dockerfile 逐行代码解析联调(.249 bigDataServer) 与 线上(.42/.43/.44) · 同一镜像运行时 -e APP_ENVtest|prod 选烧进镜像的双档配置二文件合并案 DEPLOY §2 手术件4──────────────────────────────────────────────────一、基础镜像选型与 glibc 兼容性说明# base 锁 bullseye (glibc 2.31): CentOS7 kernel 3.10seccomp 拦 glibc2.34 的 clone3 → pthread EPERM# (DEPLOY §5 头号坑, 两台宿主均 CentOS7; 万一必须升 base, 退路 --security-opt seccompunconfined)# docker.io 海外直连慢/不稳 (10-20 .249 实测拉取 4 分钟): 从零构建的机器可换国内前缀# FROM docker.m.daocloud.io/library/python:3.11-slim-bullseye — 同一枚镜像走 DaoCloud 公共代理FROM python:3.11-slim-bullseye【解析】本 Dockerfile 服务于私有化 AI Infra 引擎 v2项目。该镜像同时用于联调环境和线上环境服务器 IP 尾缀分别为 .249、.42、.43、.44。通过 Docker 运行时环境变量 APP_ENV 取值 test 或 prod 来切换配置档位属于 DEPLOY 文档第 2 节手术件 4中定义的二文件合并方案。基础镜像锁定 Debian 11 bullseye其内置 glibc 2.31。原因是部署宿主机均为 CentOS 7内核 3.10该内核的 seccomp 安全策略会拦截 glibc 2.34 引入的 clone3 系统调用导致 pthread 创建线程时报 EPERM权限拒绝错误——这是 DEPLOY 文档第 5 节标注的头号坑。万一未来必须升级到更高版本的基础镜像应急方案是启动容器时添加 --security-opt seccompunconfined 以关闭 seccomp 过滤降低安全性仅应急用。Docker Hub 默认域名 docker.io 在国内直连速度慢且不稳定在 .249 服务器上实测拉取一次需要 4 分钟。对于从零构建镜像的机器可以将 FROM 行替换为 DaoCloud 公共代理前缀FROM docker.m.daocloud.io/library/python:3.11-slim-bullseye两者指向同一枚官方镜像只是通过国内镜像加速器拉取速度更快。──────────────────────────────────────────────────二、环境变量定义ENV PYTHONUNBUFFERED1 \PIP_NO_CACHE_DIR1 \PYTHONUTF81 \TZAsia/Shanghai \APP_ENVtest【解析】设置以下环境变量PYTHONUNBUFFERED1关闭 Python 输出缓冲确保日志实时写入容器 stdout便于 docker logs 查看PIP_NO_CACHE_DIR1pip 不缓存下载包减小镜像体积PYTHONUTF81强制 Python 使用 UTF-8 编码避免中文乱码TZAsia/Shanghai设置容器时区为上海东八区APP_ENVtest应用运行环境标识默认 test运行时可通过 -e APP_ENVprod 覆盖为生产环境。──────────────────────────────────────────────────三、apt 源问题说明为何跳过 apt install# 10-20 D4 两级实测, apt 层整体绕掉: ①.249 出口到 deb.debian.org(Fastly 境外)80 不通;# ②换阿里云后索引通但 bullseye-security 文件 404 (Debian11 已 2026-08 停止常规支持, 镜像池清空索引滞后)。# 原 apt 只为装 curl(HEALTHCHECK 用)tzdata(base 镜像 python:3.11-slim 自带):# curl → 健康检查改 python urllib (镜像内必有); tzdata → 仅剩时区软链, ln 即可【解析】在 .249 和 .42 两台服务器上的实测发现两个问题问题①.249 服务器出口流量无法访问 deb.debian.org经 Fastly CDN 境外节点的 80 端口网络连接被拒。问题②更换为阿里云 apt 镜像源后索引文件虽能连通但 bullseye-security 仓库的文件返回 404。原因是 Debian 11 已于 2026 年 8 月停止常规支持EOL镜像池已清空旧索引但同步有滞后。结论直接跳过 apt 安装层。原来 apt 只需装两个包——curl用于 HEALTHCHECK 健康检查和 tzdata时区数据。但 base 镜像 python:3.11-slim 已自带 tzdata只需创建时区软链接即可而 curl 的健康检查功能可改用 Python 内置的 urllib 模块替代镜像中必然存在。因此本 Dockerfile 完全不执行 apt-get install避免网络问题导致构建失败。──────────────────────────────────────────────────四、时区设置RUN ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime【解析】通过符号链接将 /etc/localtime 指向上海时区文件效果等同于安装了 tzdata 包并设置时区为 Asia/Shanghai。参数 -f 表示强制覆盖已存在的文件-s 表示创建符号链接。这样容器内所有进程的时间戳均显示为北京时间UTC8且无需额外安装 tzdata 包减少了镜像层和网络依赖。──────────────────────────────────────────────────五、工作目录与依赖文件复制WORKDIR /appCOPY requirements.txt .【解析】WORKDIR /app将容器内的工作目录设置为 /app。后续所有 COPY、RUN、CMD 等指令的相对路径都相对于 /app也是容器启动后 shell 进入的默认目录。COPY requirements.txt .将宿主机当前目录下的 requirements.txt 文件复制到容器工作目录 /app 下。这一步单独复制依赖文件是为了利用 Docker 层缓存机制——如果 requirements.txt 未变后续的 pip install 层会命中缓存大幅加快重建速度。──────────────────────────────────────────────────六、PyTorch 安装策略说明# torch 先走 CPU 专用索引: PyPI 默认轮CUDA 捆绑 (5GB, 破 全量 2~3GB 打包结论);# 装得 2.13.0cpu 后, 后续 requirements 的 torch2.13.0 按 PEP440 视为已满足不再回拉# 10-20 用户口径「海外源大概率不通, 尽量国内」: torch 轮走上交大 pytorch-wheels 镜像# (备选 南大 https://mirror.nju.edu.cn/pytorch-wheels/cpu); pypi 走阿里云;# 国内镜像若同步滞后缺 2.13.0 版本 → 回退官方 https://download.pytorch.org/whl/cpu (443 实测可达)【解析】PyTorch 的安装策略包含三个关键设计策略①CPU 专用索引先通过 CPU 专用索引源安装 torch2.13.0cpu 版本。如果不指定 CPU 专用索引PyPI 默认提供的 wheel 包会捆绑 CUDA 运行时库额外增加约 5GB 体积破坏全量镜像 2~3GB的体积控制目标。策略②PEP440 版本匹配先用 CPU 索引装上 2.13.0cpu 版本后后续 requirements.txt 中若声明 torch2.13.0pip 按 PEP440 版本匹配规则会认为已满足依赖而不再重新拉取cpu 后缀被视为兼容版本。策略③国内镜像源优先级主选上海交大 pytorch-wheels 镜像备选南京大学镜像PyPI 通用源用阿里云最终兜底为 PyTorch 官方 CPU 轮子443 端口实测可达。──────────────────────────────────────────────────七、Python 依赖包安装RUN pip install --index-url https://mirror.sjtu.edu.cn/pytorch-wheels/cpu torch2.13.0 \ pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/【解析】分两步安装 Python 依赖第一步通过上海交大 pytorch-wheels 镜像源安装 CPU 版本的 PyTorch 2.13.0。--index-url 指定单个索引源不使用 --extra-index-url避免混入 CUDA 版本。第二步 串联第一步成功后通过阿里云 PyPI 镜像安装 requirements.txt 中列出的其余依赖。-i 指定阿里云镜像源加速下载。两步分开执行的好处是——如果只需更新业务依赖而不改 torch 版本Docker 可以复用第一步的缓存层无需重新下载 PyTorch约 200MB。──────────────────────────────────────────────────八、复制应用代码COPY . .【解析】将宿主机当前目录下的所有文件和目录递归复制到容器工作目录 /app 中。这是最后一步 COPY因为应用代码变更频率最高放在最后可以最大化利用 Docker 层缓存——只要 requirements.txt 不变后续的 pip install 层都会命中缓存。──────────────────────────────────────────────────九、端口声明EXPOSE 10021【解析】声明容器运行时监听 TCP 10021 端口。注意EXPOSE 仅做文档声明不会自动映射端口到宿主机。实际端口映射需在 docker run 时使用 -p 参数完成如 docker run -p 10021:10021或在 k8s Deployment 的 service 中配置端口映射。──────────────────────────────────────────────────十、健康检查配置# 健康检查不依赖 curl (apt 层已绕掉, 见上): 用镜像内 python 打 /health, 200healthyHEALTHCHECK --interval30s --timeout5s --start-period120s \CMD python -c import urllib.request,sys; sys.exit(0 if urllib.request.urlopen(http://127.0.0.1:10021/health,timeout4).getcode()200 else 1)【解析】配置容器健康检查Health Check让 Docker 引擎定期探测容器是否正常运行--interval30s每隔 30 秒执行一次健康检查--timeout5s检查命令执行超过 5 秒视为失败--start-period120s容器启动后给予 120 秒的宽限期应用冷启动可能需要较长时间初始化。检查命令使用Python 内置的 urllib.request 模块向容器自身 http://127.0.0.1:10021/health 端点发起 HTTP 请求。若返回 HTTP 状态码 200 则标记为 healthy若返回其他状态码或请求失败则标记为 unhealthy。不选用 curl 的原因前面跳过了 apt 安装层避免网络问题镜像中没有 curl 命令。Python 标准库的 urllib 在任何 Python 镜像中都内置可用无需额外安装。──────────────────────────────────────────────────十一、容器启动命令# SERVER_HOST/PORT(10021) 由 config 读 .env.{APP_ENV}; Linux 默认可用 proactor-free 循环,# run.py 的 Selector 策略仅 win32 生效 — 容器内与开发机同一条启动入口CMD [python, run.py]【解析】设置容器启动时执行的默认命令启动 Python 应用入口文件 run.py。补充说明服务器地址和端口10021由应用配置文件读取 .env.test 或 .env.prod 文件获取具体读取哪个文件取决于运行时环境变量 APP_ENV 的值。run.py 中包含的 Selector 策略事件循环选择器仅对 Windows 系统生效在 Linux 容器环境和开发机通常也是 Linux上Python 默认使用 proactor 事件循环因此容器内和生产开发环境使用同一条启动命令即可无需区分平台。──────────────────────────────────────────────────十二、关键设计决策总结设计决策原因基础镜像选 bullseyeCentOS7 宿主机 kernel 3.10 不兼容 glibc2.34 的 clone3 调用不用 apt install.249 服务器无法访问 deb.debian.org阿里云镜像 bullseye-security 文件 404不用 curl 做健康检查apt 层已跳过镜像内无 curl改用 Python 内置 urllibtorch 走 CPU 专用索引避免 PyPI 默认 wheel 捆绑 CUDA 运行时5GB控制镜像体积在 2~3GB国内镜像源优先海外源大概率不通主选交大镜像备选南大/阿里云/官方时区设置用 ln 软链不装 tzdata 包也能设置时区减少镜像层和网络依赖2、操作命令tar -xzf pkai_src_v0.1_*.tar.gzcd /opt/wqo_python/python_knowlage_ai/docker rm -f ai-agentdocker rmi aiinfra-engine:v0.1有问题的镜像可以删除cd /opt/wqo_python/python_knowlage_aidocker build -t aiinfra-engine:v0.1 .docker build -t aiinfra-engine:v0.1 .docker images先看 10021 是否被占、有无同名残留容器:docker ps -a --filter nameai-agentss -lntp | grep 100211. 开发机推模型(约 809M rerank 565M embed 184M cv 60M):rz -edocker rm -f ai-agentdocker 启动命令docker run -d --name ai-agent --restartunless-stopped -p 10021:10021 --memory4g -e APP_ENVtest --log-opt max-size100m --log-opt max-file5 -v /opt/wqo_python/models:/app/models:ro -v /opt/wqo_python/logs:/app/logs aiinfra-engine:v0.1docker run -d --name ai-agent --restartunless-stopped -p 10021:10021 --memory4g -e APP_ENVtest --log-opt max-size100m --log-opt max-file5 -v /opt/wqo_python/models:/app/models:ro -v /opt/wqo_python/logs:/app/logs aiinfra-engine:v0.1docker logs -f ai-agent在本地测试set PYTHONUTF81 .venv\Scripts\python.exe scripts\smoke_agent_http.py http://192.168.1.249:10021----------------------------------------------------------------------------------------------------------------更新镜像的操作docker run -d --name ai-agent --restartunless-stopped -p 10021:10021 --memory4g -e APP_ENVtest --log-opt max-size100m --log-opt max-file5 -v /opt/wqo_python/models:/app/models:ro -v /opt/wqo_python/logs:/app/logs aiinfra-engine:v0.1cd /opt/wqo_python/python_knowlage_ai docker build -t aiinfra-engine:v0.1 . docker rm -f ai-agent docker run -d --name ai-agent --restartunless-stopped -p 10021:10021 --memory4g -e APP_ENVtest --log-opt max-size100m --log-opt max-file5 -v /opt/wqo_python/models:/app/models:ro -v /opt/wqo_python/logs:/app/logs aiinfra-engine:v0.1 docker images -a | grep aiinfra # v0.1新ID, 另有一行 none旧镜像 docker image ls -f danglingtrue # 单看无名的 # 按 ID 删单枚(最精确, 比如咱自己的旧 v0.1 残影) docker rmi 5f6c03434f78cd /opt/wqo_python/python_knowlage_ai -------待验证bash scripts/deploy_test.sh2、.244 部署方案与计划 -------------待讨论244上mkdir -p /opt/wqo_python/{models,logs}上传 models.zipunzip models.zip【镜像搬运】249 上 docker save aiinfra-engine:v0.1 | gzip → scp 244 → docker load§7 ship 口径千兆内网约 1 分钟级。docker save aiinfra-engine:v0.1【起容器】照 deploy_test.sh 的 run 段-e APP_ENVtest、双卷、4g、log-opt。小手术给 deploy_test.sh 加个 SKIP_BUILD1 开关即可复用当前脚本 build 是死步不加就手工 run。【验收】curl :10024:10021/health 全绿 → 开发机 smoke_agent_http.py http://192.168.1.244:10021 36 项 → verify_agent_contract.py --db → 沙盒平方和项依 248:2375 通→ eval_rag --limit 2 护基线 0.982/5.000。