Docker Compose 报外部网络不存在
Docker Compose 找不到声明为 external 的网络。核对实际网络名和 Docker Engine,按跨项目共享或项目内部使用选择创建网络、修正引用或交给 Compose 管理,并检查容器接入和业务连接。
运行 docker compose up 时,镜像已经准备好,容器却没有按预期启动,终端停在这条错误上:
network shared_backend declared as external, but could not be found
这条报错表示 Compose 没有在当前连接的 Docker Engine 中找到它要使用的外部网络。继续构建镜像通常不会改变这个结果;要核对的是网络是否存在、配置引用的真实名称,以及创建网络和启动项目的命令是否连接了同一个 Engine。
下面使用当前的 docker compose 插件命令,处理单个 Engine 上的 Linux 容器及桥接网络,不用于修复 Swarm 的跨主机 overlay 网络。
external 不会替项目创建网络
以下配置要求网络已经存在:
networks:
shared:
external: true
name: shared_backend
shared 是这份 Compose 文件里的逻辑键,服务的 networks 列表引用它;shared_backend 是 Engine 上已有网络的实际名称。external: true 要求 Compose 使用已有资源,网络不存在就报错。name 会按原值使用,不再附加项目名前缀。
如果没有填写 name,这个外部网络声明会查找名为 shared 的网络。另一份 Compose 项目创建的网络却可能叫 otherproject_shared,两个名字不能互换。
这里的“外部”指网络由这个项目之外维护,并不表示容器已经向公网开放端口。是否发布端口仍取决于服务的端口配置和实际网络环境。
把配置中的网络名与 Engine 上的资源对上
先在启动项目的同一终端确认工具和连接目标:
docker compose version
docker context show
docker context ls
Context 列表包含 Docker endpoint。还要检查当前终端是否设置了 DOCKER_HOST、DOCKER_CONTEXT,以及原启动命令是否用了 --host 或 --context。这些设置可能让命令连接另一个 Engine;只看到某个 context 带星号,不能忽略显式参数和环境覆盖。
下文的 target-context 是占位值,替换为你已经确认的 context 名。所有检查和修改都显式指定它,避免在本机创建网络、却在远程服务器启动项目。若原部署使用 --host 和相应 TLS 参数,应沿用那组已确认的连接参数。
读取最终配置时,保留真实部署使用的全部 -f、--env-file、项目名称和目录参数。下面以单个 compose.yaml 为例,只打印网络部分,避免把整份渲染结果里的环境变量一并输出;需要 Bash 或 Zsh,以及 Python 3:
(
set -o pipefail
docker --context target-context compose -f ./compose.yaml config --format json |
python3 -c '
import json, sys
model = json.load(sys.stdin)
print(json.dumps(model.get("networks", {}), ensure_ascii=False, indent=2))
'
)
检查每个网络的 external 和 name。这一步能发现多份文件合并、变量插值后,网络名与手边那份 YAML 不一致的情况。它只解析配置,不证明外部网络真的存在,也不会启动容器。
再查同一个 Engine 的资源:
docker --context target-context network ls
docker --context target-context network inspect shared_backend
shared_backend 也要替换为刚才解析出的真实名称。inspect 成功时,核对 Name、Id、Driver、Scope、IPAM 和 Containers,确认这是预期网络,而不只是恰好同名的资源。网络列表和检查结果含内部地址,发给别人前应脱敏。
配置和资源检查结果对应不同处理:
| 结果 | 对应处理 |
|---|---|
预期网络已存在,但 Compose 的 name 不同 |
修正引用名,保留原网络 |
| 网络只存在于另一台 Engine | 修正部署目标;不要在错误目标上补建网络 |
| 确实没有网络,且它应供多个项目共享 | 在目标 Engine 创建一次,再让各项目引用 |
| 网络只供本项目内部服务使用 | 改为 Compose 管理的网络,或使用项目默认网络 |
跨项目共享时,保留外部网络声明
反向代理与应用分属不同 Compose 项目,并且应直接通过容器网络通信时,可以使用同一个外部网络。只有确认网络确实不存在、部署目标正确、所需驱动是单机 bridge,且没有另外约定子网或网络选项时,才按下面方式创建:
docker --context target-context network create --driver bridge shared_backend
docker --context target-context network inspect shared_backend
这是资源修改操作。若原部署有固定子网、网关、IPv6 或其他驱动要求,应从原配置恢复这些参数;随手创建一个同名普通桥接网络,不能恢复原有网络拓扑。桥接网络只连接同一个 Docker daemon 主机上的容器。
需要互通的项目都引用同一个真实名称。应用侧的网络配置例如:
services:
app:
image: your-registry.example/app:your-tag
networks:
- shared
- default
networks:
shared:
external: true
name: shared_backend
default: {}
这是网络结构示例。镜像是占位值,实际应用的环境变量、数据卷、端口及其他服务应保留原配置。另一个项目中,需要访问应用的服务也应接入 name: shared_backend 的外部网络;它的逻辑键可以不同,最终网络名必须一致。
不要把所有数据库和缓存都接到共享网络来省事。默认情况下,同一用户自定义桥接网络中的容器可以访问彼此的端口,即使那些端口没有发布到宿主机。只接入需要跨项目通信的服务,保留其他服务原有的隔离范围。
外部网络声明只保留 external 和需要的 name。不要在同一声明下追加 driver: bridge、ipam 等创建参数;当前规范会把这类组合判为无效。创建参数应交给维护这个外部网络的命令或部署流程。
只有一个项目时,让 Compose 管理网络
如果这条网络只供本项目使用,没有代理或其他项目依赖它,可以把外部声明改为项目管理的网络。服务仍引用逻辑键 shared,顶层配置改成:
networks:
shared: {}
同时去掉原来的固定 name,让 Compose 按项目名称管理网络。没有显式网络需求时,也可以移除服务级及顶层的自定义网络声明,使用 Compose 自动创建的 <project-name>_default 网络。Compose 创建的这种网络同样属于用户自定义桥接网络,并不需要额外手工创建才能让服务按名称互相访问。
这个选择会改变资源的归属:项目管理的网络通常会随 docker compose down 移除,而声明为外部的网络不会。若其他项目仍依赖原网络,删除 external 后即使启动成功,也可能让它们与应用分离。
不要把引用名直接改成 Engine 自带的 bridge 来消除报错。默认 bridge 与 Compose 为项目创建的用户自定义网络不同,前者没有同样的容器名称自动解析行为,可能让后续的服务名解析失败。
更新容器后确认实际接入情况
保存原 Compose 文件和部署参数,确认数据卷仍指向原位置;涉及已有数据库等持久化服务时,先准备可用的数据备份。已有服务的网络配置变更可能触发容器重建,连接会中断,应安排维护窗口;首次启动失败的项目,也要确认是否已有部分服务启动。
在目标 Engine 验证配置,然后沿用相同参数更新项目:
docker --context target-context compose -f ./compose.yaml config -q
docker --context target-context compose -f ./compose.yaml up -d
前一条命令验证配置,后一条会创建、启动或重建容器。up 重建时保留已挂载的卷,但这不代表修改项目名或卷挂载后仍会接到原数据。
共享网络方案可以用以下命令查看接入成员:
docker --context target-context network inspect shared_backend \
--format '{{range .Containers}}{{println .Name}}{{end}}'
确认应用和另一个项目中需要通信的服务都在其中。项目管理方案则检查实际生成的网络名。接着从原来失败的应用或代理建立新的业务连接,使用服务名和容器内部端口,检查实际响应及应用日志;网络存在、容器接入都只是前置条件,不能替代业务连通验收。
如果接入后仍出现名称解析失败或连接拒绝,要分别查服务别名、监听端口和应用就绪状态。此时网络已存在,反复创建网络不会帮助定位这些新错误。
回退时恢复原配置、原项目名称及原连接目标,再用相同部署参数更新受影响服务。保留已经存在的共享网络;若本次新建的网络不再需要,只有在所有使用方确认退出、检查结果没有连接容器后,才按确切名称或 ID 单独删除。Docker 要求先断开网络上的容器才能删除网络,不应为了清理而断开仍在使用它的其他项目。
如果删除时仍报 active endpoints,可按共享网络仍有容器连接的检查方法确认剩余端点及其所属项目。


