Docker Compose 解决服务间 DNS 解析失败问题

前言

在使用 Docker Compose 部署微服务架构时,发现部分服务无法通过容器名称解析其他服务,导致服务启动失败并进入重启循环。

问题现象

初始错误

启动 Docker Compose 时,出现以下错误:

bash 复制代码
docker compose --env-file .env --env-file .env.image.amd64 up -d
✘ Container elastic-wanwu       Error dependency es failed to start

服务重启循环

多个服务出现重启循环,日志显示 DNS 解析失败:

json 复制代码
{"level":"FATAL","ts":"2026-01-06T07:12:05.681Z","caller":"assistant-service/main.go:56","msg":"init redis err: dial tcp: lookup redis-wanwu: i/o timeout"}
{"level":"FATAL","ts":"2026-01-06T07:11:36.091Z","caller":"iam-service/main.go:58","msg":"init redis err: dial tcp: lookup redis-wanwu: i/o timeout"}

问题排查过程

1. 首先解决 Elasticsearch 启动问题

Elasticsearch 容器日志显示:

复制代码
bootstrap check failure [1] of [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

解决方案:

bash 复制代码
# 永久修复
echo 'vm.max_map_count=262144' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

2. 网络连接状态检查

检查 Docker 网络配置:

bash 复制代码
docker network ls | grep wanwu
docker network inspect wanwu-net

发现网络配置正常,所有容器都正确连接到 wanwu-net 网络并获得了 IP 地址。

3. DNS 解析测试

使用测试容器验证 DNS 解析:

bash 复制代码
docker run --rm --network wanwu-net alpine:latest nslookup redis-wanwu

结果显示:

复制代码
;; connection timed out; no servers could be reached

这表明问题出在 DNS 解析层面。

4. Docker 守护进程配置检查

检查 Docker 服务状态:

bash 复制代码
sudo systemctl status docker

发现 Docker 守护进程配置了有问题的 DNS 设置:

复制代码
--dns 10.233.0.3 --dns 127.0.0.53 --dns-search default.svc.cluster.local --dns-search svc.cluster.local

这些 Kubernetes 相关的 DNS 配置导致容器内的 DNS 解析失败。

根本原因分析

问题的根本原因是 Docker 守护进程配置了不当的 DNS 设置,这些设置来自于系统中的多个配置文件:

  • /etc/systemd/system/docker.service.d/docker-dns.conf
  • /etc/systemd/system/docker.service.d/docker-options.conf
  • /etc/systemd/system/docker.service.d/override.conf

这些配置文件中的 DNS 设置(特别是 Kubernetes 集群的 DNS)在非 Kubernetes 环境中无法正常工作,导致容器内的 DNS 解析完全失败。

解决方案

方案一:临时解决 - 使用 IP 地址

bash 复制代码
# 获取 Redis 容器的 IP 地址
docker inspect redis-wanwu | grep IPAddress

# 修改环境变量,使用 IP 地址替代主机名
cp .env.bak .env.temp
sed -i 's/redis-wanwu/172.18.0.4/g' .env.temp

# 重启服务
docker compose --env-file .env.temp --env-file .env.image.amd64 restart bff-service iam-service assistant-service

方案二:根本解决 - 清理 Docker DNS 配置

  1. 查看现有配置文件:
bash 复制代码
ls -la /etc/systemd/system/docker.service.d/
cat /etc/systemd/system/docker.service.d/docker-dns.conf
  1. 备份并禁用有问题的 DNS 配置:
bash 复制代码
# 备份现有配置
sudo cp /etc/systemd/system/docker.service.d/docker-dns.conf /etc/systemd/system/docker.service.d/docker-dns.conf.bak

# 临时禁用 DNS 配置
sudo mv /etc/systemd/system/docker.service.d/docker-dns.conf /etc/systemd/system/docker.service.d/docker-dns.conf.disabled
  1. 重启 Docker 服务:
bash 复制代码
sudo systemctl daemon-reload
sudo systemctl restart docker
  1. 重新启动应用服务:
bash 复制代码
docker compose --env-file .env --env-file .env.image.amd64 up -d

验证解决方案

解决后,可以通过以下方式验证:

  1. 检查容器状态:
bash 复制代码
docker ps
  1. 测试 DNS 解析:
bash 复制代码
docker run --rm --network wanwu-net alpine:latest nslookup redis-wanwu
  1. 查看服务日志:
bash 复制代码
docker logs assistant-service --tail 10
docker logs iam-service --tail 10

经验总结

问题诊断思路

  1. 分层排查:从基础设施(Elasticsearch)到网络层(DNS)逐步排查
  2. 日志分析:通过容器日志快速定位问题类型
  3. 网络测试:使用简单的测试容器验证网络连通性
  4. 配置检查:检查 Docker 守护进程的配置参数

预防措施

  1. 环境隔离:避免在非 Kubernetes 环境中使用 Kubernetes 相关的 DNS 配置
  2. 配置管理:定期检查和清理不必要的 Docker 配置文件
  3. 监控告警:建立容器健康检查和 DNS 解析监控

适用场景

这个解决方案适用于以下场景:

  • Docker Compose 服务间无法通过容器名称互相访问
  • 容器内 DNS 解析超时或失败
  • 在混合环境(Kubernetes + Docker Compose)中出现的 DNS 冲突

通过彻底清理 Docker 的 DNS 配置,我们成功解决了服务间的网络通信问题,所有微服务都能正常启动并相互通信。

相关推荐
Leinwin5 小时前
OpenClaw 多 Agent 协作框架的并发限制与企业化规避方案痛点直击
java·运维·数据库
2401_865382505 小时前
信息化项目运维与运营的区别
运维·运营·信息化项目·政务信息化
漠北的哈士奇5 小时前
VMware Workstation导入ova文件时出现闪退但是没有报错信息
运维·vmware·虚拟机·闪退·ova
如意.7596 小时前
【Linux开发工具实战】Git、GDB与CGDB从入门到精通
linux·运维·git
运维小欣6 小时前
智能体选型实战指南
运维·人工智能
yy55276 小时前
Nginx 性能优化与监控
运维·nginx·性能优化
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ7 小时前
Linux 查询某进程文件所在路径 命令
linux·运维·服务器
05大叔9 小时前
网络基础知识 域名,JSON格式,AI基础
运维·服务器·网络
安当加密9 小时前
无需改 PAM!轻量级 RADIUS + ASP身份认证系统 实现 Linux 登录双因子认证
linux·运维·服务器
dashizhi20159 小时前
服务器共享禁止保存到本地磁盘、共享文件禁止另存为本地磁盘、移动硬盘等
运维·网络·stm32·安全·电脑