#MTPhotos #Docker #DNS #腾讯地图 #N100

记录 MT Photos 从高德地址解析迁移到腾讯地图时,如何把表面的 API 超时拆成容器 DNS 与签名配置两层问题,并将临时 resolver 修复固化为可重建、可重启的 Docker 配置。

相关《MT Photos 语义检索接入 RAG 可行性分析》 · 《N100 网络重构与服务修复记录》


一、问题不是单一的“腾讯 API 不通”

MT Photos 已切换到腾讯地图 provider,但 GUI 对固定公开坐标执行测试时返回 network timeout。分层探针得到的结果并不支持“腾讯接口故障”这个直觉判断:

层级 N100 宿主 MT Photos 容器
DNS 正常 UDP 查询超时,TCP 查询成功
TCP 443 正常 使用已解析 IPv4 地址可达
TLS/SNI 正常 正常
无凭据 HTTPS HTTP 200 HTTP 200

容器对腾讯和通用对照域名都会在普通 DNS 查询阶段超时,因此故障并非腾讯单域名规则。一次性设置 RES_OPTIONS=use-vc 后,同版 Node 运行时立即可以完成 DNS 和 HTTPS 请求,说明真正的网络根因是:容器使用的 resolver 无法正常收到 UDP/53 响应,但 TCP DNS 可用。

DNS 修复后还暴露出第二层问题:MT Photos 中保存的签名 secret 与当前有效配置不一致。两层故障此前被同一个 timeout 表象遮蔽,必须按 DNS → TLS/HTTP → API 签名顺序验证,不能直接修改代理或防火墙。

二、签名验收的安全边界

腾讯地图 WebService 的签名请求包含敏感参数。本次验收采用以下边界:

  • 凭据只由用户在既有 GUI 中保存,agent 不读取或复制值;

  • 不使用会把 Key、secret 或签名放入 URL 路径的不安全测试入口;

  • 只使用固定公开坐标,不读取照片 GPS、地址或数据库正文;

  • 证据只保存 HTTP 状态、API 状态、字段存在性和延迟;

  • 日志审计只返回是否命中敏感模式的布尔值。

完成配置更新后,公开坐标的逆地址解析返回 HTTP 200、API status 0,并具备行政区划、街道、adcode 和配额元数据。凭据、签名串和地址正文均未进入报告。

三、为什么不能只改容器内 resolv.conf

直接在运行中容器的 /etc/resolv.conf 追加:

1
options use-vc

可以立即恢复服务,但它不是持久方案。Docker 在容器创建或启动时会重新生成 resolver 文件,手工修改可能在 recreate 或 restart 后消失。

最终方案把 TCP DNS 写入容器声明式配置:

1
2
3
{
"DnsOptions": ["use-vc"]
}

迁移采用 copy-first 的受控重建方式:先冻结原镜像、环境摘要、三个 bind mount、端口、bridge 网络、设备、restart policy、入口命令和数据路径元数据,再创建等价新容器。唯一预期差异是新增 DnsOptions=["use-vc"]

四、重建过程中的两个验收器陷阱

1. 启动时序不能用单点判断

新容器 HTTP 已就绪时,DNS 相关进程仍可能处于短暂初始化阶段。因此最终验收使用最长 60 秒的有界退避,而不是第一次失败就判定声明式配置无效。

2. Docker SDK 可能制造假阴性

一次验收中,命令正文已经把输出重定向到 /dev/null,但 Docker SDK 在关闭 stdout/stderr 通道时返回空退出码。验收器将空值误判为 DNS 失败并触发回滚。

修复只打开 SDK 输出通道以取得确定退出码,实际命令仍不输出 DNS 正文。修复后重建、DNS、HTTP 和签名验收全部通过。这说明生产维护脚本必须区分:

  • 被测服务失败;

  • 远端输出通道失败;

  • 验收客户端无法取得退出码。

三者不能共用一个失败类别。

五、最终持久化证据

最终生产容器保持原镜像,挂载、端口、网络、设备、业务配置与数据路径元数据均无漂移。完成以下两类验证:

Recreate 验收

  • 新容器运行正常;

  • DnsOptions=["use-vc"]

  • resolver 只有一条 use-vc

  • 腾讯和通用对照 DNS 正常;

  • 管理入口 HTTP 200;

  • 固定公开点签名请求 HTTP 200、API status 0。

主动 restart 验收

随后只执行一次 docker restart mt-photos。容器 ID 与镜像保持不变,StartedAt 变化证明 restart 实际发生。重启后:

  • 声明式 DnsOptions 仍存在;

  • resolver 仍为单条 use-vc

  • DNS、管理入口和公开点签名请求继续全绿;

  • 三个 bind、端口、bridge、设备和数据路径元数据无漂移;

  • 日志未出现 Key、secret 或签名查询串。

独立只读审核最终为 P0/P1/P2=0。旧回滚容器在证据闭合后精确删除,bind 数据和生产镜像继续保留。

六、可复用结论

  1. API timeout 应先按 DNS、TCP、TLS、HTTP、签名逐层定位,避免直接归因代理或服务端。

  2. 容器 UDP DNS 失败而 TCP DNS 正常时,use-vc 可以作为有界修复,但必须进入声明式容器配置。

  3. “配置存在”不等于持久化完成;至少要分别证明 recreate 与 restart 后仍有效。

  4. 生产验收器必须把服务失败与 SSH、stdout、SDK exit-code 采集失败分开。

  5. 含签名参数的 API 验收应使用公开测试对象、字段白名单和布尔日志审计,避免凭据与私人地址进入证据链。

宿主完整重启后的恢复可并入 N100 整机恢复演练,不需要为单一容器额外重启主机。