docker-compose重建db容器后报无法链接非运行容器错误排查
问题核心原因
你的配置错误本质是混用了Docker已淘汰的旧版链接机制,同时主动放弃了Docker Compose自带的服务发现能力,具体问题点:
- 手动给两个服务配置
network_mode: bridge,会直接跳过Docker Compose默认创建的项目专属隔离网络,把两个容器直接挂到Docker全局默认的bridge网络上。这个全局默认bridge网络没有内置DNS服务发现能力,你第一次启动能连通数据库,完全靠external_links触发的旧版Docker Legacy Link功能,根本不是正常的域名解析生效。 - 旧版Docker Link是静态绑定关系:容器启动时会直接把被链接容器的当前容器ID写入到自己的链接配置里,完全不支持动态更新。你第一次全量执行
docker-compose up时,postgres容器先启动,web容器启动时链接到当时运行的postgres容器ID,所以连接正常。但你单独重建db容器时,新启动的postgres容器会分配全新的容器ID,web容器里留存的还是旧容器的绑定记录,旧容器已经被销毁,自然会抛出Cannot link to a non running container: /postgres AS /web/postgres的错误。 - 配置本身存在逻辑矛盾:
depends_on声明的依赖是名为db的Compose服务,但external_links写的是硬链接名为postgres的独立容器,完全脱离Compose的生命周期管理,Compose不会在你重建db容器时自动更新web的链接关系。
修复方法
按下面的步骤调整配置就能彻底解决问题:
- 删除两个服务下的
network_mode: bridge配置,同时删除web服务下的external_links配置。两个服务会默认加入Compose自动创建的项目专属网络,这个网络自带内置DNS,支持通过服务名直接做域名解析,不需要任何额外链接配置。 - 把web容器里的数据库连接地址从
host=postgres改成host=db——这里的db就是Compose配置里定义的数据库服务名,只要服务在同一个专属网络里,这个地址永远可以正常解析,不管容器怎么重建、容器ID怎么变都不会失效。 - 修正后的核心配置片段参考:
version: '3.8' services: db: image: postgres:14.1 container_name: postgres volumes: - postgres_data:/var/lib/postgresql/data/ # 补充你自己的数据库配置,比如POSTGRES_PASSWORD、POSTGRES_DB等环境变量 web: container_name: web build: . depends_on: - db # 此处数据库连接配置直接用host=db即可 volumes: postgres_data: name: postgres_data
- 额外提醒:如果你的web服务是启动时就初始化数据库连接、没有自动重连逻辑,单独重建db之后可能会出现短暂的连接报错,给数据库连接逻辑加几轮重试就可以解决,不会再出现找不到容器的底层错误。
内容的提问来源于stack exchange,提问作者AlexanderKondrat
相关产品推荐
相关产品推荐

