Docker Swarm多主机环境下.NET应用连接Postgres数据库报错求助
Docker Swarm多主机部署.NET+Postgres网络问题解决
问题现象
单主机部署时.NET应用与Postgres数据库通信正常,切换到Swarm多主机环境后,应用抛出SocketException:
2022-12-22 22:44:24 Unhandled exception. System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (00000001, 11): Resource temporarily unavailable 2022-12-22 22:44:24 at System.Net.Dns.GetHostEntryOrAddressesCore(String hostName, Boolean justAddresses, AddressFamily addressFamily, ValueStopwatch stopwatch) ...(省略中间栈信息) 2022-12-22 22:44:24 at Program.<Main>$(String[] args) in /src/TimeManager.API/Program.cs:line 51
需求是将Postgres固定部署在某台单独主机,Windows Docker Desktop环境无法使用--network host模式,现有docker-compose.yml配置如下:
version: '3.4' services: timemanagerapi: image: ****/timemanagerapi:latest restart: always ports: - 80:80 depends_on: - postgresserver postgresserver: image: postgres environment: - POSTGRES_PASSWORD=****** volumes: - pgdata:/var/lib/postgresql/data ports: - 5432:5432 volumes: pgdata:
问题原因
默认的Docker bridge网络是单主机范围的,跨主机的Swarm服务无法通过该网络实现服务发现与通信;同时未对数据库服务设置部署约束,导致Swarm可能将数据库调度到任意节点,且应用无法跨主机解析数据库服务名。
解决方案
1. 创建Swarm Overlay网络
Overlay网络是Swarm跨主机通信的核心,先创建一个全局可用的overlay网络:
docker network create --driver overlay timemanager-network
2. 修改docker-compose.yml配置
更新配置,指定使用overlay网络,同时给数据库添加部署约束固定到目标主机:
version: '3.4' services: timemanagerapi: image: ****/timemanagerapi:latest restart: always ports: - 80:80 depends_on: - postgresserver networks: - timemanager-network deploy: replicas: 1 # 根据需求调整副本数 postgresserver: image: postgres environment: - POSTGRES_PASSWORD=****** volumes: - pgdata:/var/lib/postgresql/data networks: - timemanager-network deploy: placement: constraints: - node.hostname == 你的数据库主机名 # 替换为实际主机名 replicas: 1 volumes: pgdata: networks: timemanager-network: external: true # 指定使用已创建的外部网络
3. 关键配置说明
- Overlay网络:所有服务加入同一个overlay网络,Swarm会自动提供跨主机的服务发现,应用可以直接通过服务名
postgresserver访问数据库 - 部署约束:通过
node.hostname将数据库固定到指定主机,避免Swarm调度到其他节点 - 端口映射:移除数据库的
5432:5432端口映射,服务间通信无需暴露主机端口,提升安全性
4. 验证连接字符串
确保.NET应用的数据库连接字符串使用服务名而非IP/localhost:
Server=postgresserver;Port=5432;Database=你的数据库名;User Id=postgres;Password=你的密码;
5. 部署服务
使用Swarm栈命令部署:
docker stack deploy -c docker-compose.yml timemanager
6. 检查节点连通性
确保Swarm所有节点之间开放以下端口:
- TCP/UDP 7946:节点间通信与集群管理
- UDP 4789:Overlay网络数据包传输
内容的提问来源于stack exchange,提问作者Avusar
相关产品推荐
相关产品推荐

