DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

Compose 共享外部网络后,db 偶尔连到另一个项目

共享外部网络上的db别名可能同时属于两套数据库。对照实际Aliases和IP,改用唯一目标或保留私有网络,并验收数据环境。

两个 Compose 项目各有自己的数据库,应用却偶尔报用户名不对、数据库不存在,甚至读到另一套环境的数据。重建容器后表现还会变化。若两个项目都把名为 db 的服务接入同一张外部网络,先检查这张网上是否存在重复的 db 别名。

Compose 会在服务接入的网络上提供服务名别名。项目名不同、容器名带不同前缀,都不等于共享网络中的 db 已被隔离。一个网络别名可以属于多个容器,此时名称到底解析到哪一个容器没有保证。

下面针对单机 Linux 容器与 Compose V2 的共享网络,按 v2.40.3 的别名行为说明,不涉及 Swarm 服务发现。此分支需要确认重复别名,不能用它解释所有数据库连接失败。

对照应用和两套数据库的实际网络

先记录应用真正使用的数据库主机名,再在 Docker 主机上只读检查容器。名称均为示例:

docker inspect app-1 db-1 db-2 \
  --format '{{.Name}} {{json .NetworkSettings.Networks}}'

docker network inspect app_shared

将名称换成实际容器与网络。对照每个网络中的 Aliases、容器 IP 及网络成员,检查两套数据库是否同时在 app_shared 上具有 db 别名,发起请求的应用是否也接入了它。信息可能包含内部地址,应保存在受控记录中。

应用镜像已有 getent 时,可以从发起连接的容器查询:

docker exec app-1 getent hosts db

没有这个工具,就用应用已有的名称查询能力,不必临时给生产镜像安装工具。把返回地址与前面的网络 IP 对应起来;一次查询碰巧命中正确数据库,不足以排除重复别名。

如果只有一个目标容器拥有该名称,或者应用根本不使用 db,继续检查实际地址、认证配置和后端就绪状态。不要因为共享网络存在,就认定登录失败一定来自别名碰撞。

自定义 aliases 不会替换服务名

假设服务配置已经加了独有别名:

services:
  db:
    networks:
      shared:
        aliases:
          - project1-db

networks:
  shared:
    external: true
    name: app_shared

这是现有配置的网络片段,镜像、数据卷、凭据等字段仍需保留。project1-db 会作为附加别名加入,自动生成的 db 不会因此消失。应用继续连接 db 时,碰撞仍可能存在。

external: true 规定网络生命周期由项目外部管理,不会为每个项目划分名称空间。只修改 -p 项目名或 container_name,也不能消除共享网络上重复的服务名别名。

按通信需求选择网络和目标名称

如果数据库只服务于本项目,优先让每个项目的数据库留在自己的私有网络,只把确实需要代理或隧道访问的应用接入共享网络。要一起检查所有相关项目,避免另一个数据库仍在共享网上提供同名别名。

确实需要跨项目访问数据库时,为目标设置在这张网上唯一的别名,并将消费者的实际数据库地址改成该别名。例如第一套数据库使用 project1-db,另一套使用不同名称;同时检查是否已有别的服务占用这些名称。

唯一别名解决目标辨认,不会限制其他容器访问数据库。共享网络扩大了通信范围,是否应该共享仍需按业务边界判断,也不需要为此新增数据库公网端口。

保存 Compose 清单、应用地址和网络关系,核对数据库数据卷及备份后,在维护窗口应用变更。更新网络配置通常需要重新创建受影响服务;只重启现有容器,不会重新生成网络端点的别名。共享网络仍被其他项目使用时,不要删除它,相关生命周期问题可看 active endpoints 与外部网络配置。

验收连接到的是哪套数据

更新后先核对别名和网络成员,再从实际应用连接数据库,确认数据库名、环境标识或已知业务记录属于目标环境。仅能解析名称、TCP 连接成功或登录成功,都不能证明没有连错库。

还应检查应用到缓存、代理和其他依赖的连接,并在正常重建后再次确认目标选择。若出现回归,恢复已保存的网络与应用地址配置,再核验业务;配置回退不会撤销此前误写入另一套数据库的数据,这部分需要单独核对和恢复。