多Compose文件部署Docker Swarm时healthcheck服务名解析失败
问题背景
我有三个Docker Compose配置文件:main.yml、prod.yml,以及手动合并了两者内容的commonmainprod.yml。其中webui服务的核心配置如下:
services: webui: container_name: webuiprice${APP_ENV_PROD:-prod} image: ${REGISTRY_ADDR}/price/webui:${APP_ENV_PROD:-prod}_sw_${VERSION:-0.1.0} # 其他配置省略
Healthcheck规则配置:
test: curl --fail http://webui:8090 || exit 1 interval: 60s retries: 5 start_period: 20s timeout: 10s
容器内no_proxy环境变量配置:
no_proxy == 'localhost,webui,price-prod_webui
现象差异
多文件部署时Healthcheck失败
执行部署命令:
docker stack deploy -c main.yml -c prod.yml stack-prod
Healthcheck报错,curl无法解析服务名:
curl --fail http://webui:8090 -v * Uses proxy env variable no_proxy == 'localhost,webui,price-prod_webui' * Could not resolve host: webui * Closing connection 0 curl: (6) Could not resolve host: webui
单合并文件部署时Healthcheck正常
执行部署命令:
docker stack deploy -c commonmainprod.yml stack-prod
Healthcheck正常连通:
curl --fail http://webui:8090 -v * Uses proxy env variable no_proxy == 'localhost,webui,price-prod_webui' * Trying 10.0.2.216:8090... * Connected to webui (10.0.2.216) port 8090 (#0) > GET / HTTP/1.1 > Host: webui:8090 > User-Agent: curl/7.88.1 > Accept: */*
补充现象
prod栈启动后,Healthcheck最初一直报curl: (6) Could not resolve host: webui错误。但当我启动另一个test栈(其webui服务的Healthcheck用test: curl --fail http://localhost:8090)并正常运行后,prod栈的webui服务Healthcheck突然恢复正常。
prod栈使用的Overlay网络:
network1: name: traefik-reverse-proxy external: true network2: name: price-net-prod external: true
test栈使用的Overlay网络:
network1: name: traefik-reverse-proxy external: true network2: name: price-net-test external: true
原因分析
1. Compose多文件合并的网络配置冲突
多文件部署时,main.yml和prod.yml中如果对webui服务的网络关联配置存在覆盖或缺失,可能导致容器启动时未正确加入price-net-prod网络,或者Swarm服务的DNS别名未在网络中注册。而手动合并的单文件是完整的统一配置,网络关联逻辑明确,容器能正常获取服务名解析。
2. Swarm内置DNS的同步延迟
Swarm的DNS服务是异步注册服务记录的,多文件部署时可能因服务启动顺序、网络初始化延迟等问题,导致容器启动初期无法解析webui服务名。test栈启动后,可能触发了Swarm DNS的服务记录刷新,或者新增的网络活动让DNS服务重新同步了网络内的服务信息,间接修复了prod栈的解析问题。
3. 环境变量合并的语法问题
你当前的no_proxy配置末尾缺少闭合单引号,多文件部署时这种语法错误可能被Compose合并过程放大,导致curl实际未正确应用no_proxy规则,仍尝试走代理而非使用Swarm DNS。而手动合并的单文件可能你已经修复了这个错误,所以解析正常。
验证建议
- 检查
main.yml和prod.yml中webui服务的网络配置,确保两个文件的网络定义无冲突,且webui明确关联了price-net-prod网络。 - 修复
no_proxy的语法错误(添加末尾的'),重新用多文件部署测试。 - 多文件部署后,手动进入
webui容器执行nslookup webui,查看DNS解析结果是否正常。
内容的提问来源于stack exchange,提问作者Konstantin

