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

前言

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

问题现象

初始错误

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

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

服务重启循环

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

{"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]

解决方案:

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

2. 网络连接状态检查

检查 Docker 网络配置:

docker network ls | grep wanwu
docker network inspect wanwu-net

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

3. DNS 解析测试

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

docker run --rm --network wanwu-net alpine:latest nslookup redis-wanwu

结果显示:

;; connection timed out; no servers could be reached

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

4. Docker 守护进程配置检查

检查 Docker 服务状态:

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 地址

# 获取 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. 查看现有配置文件:
ls -la /etc/systemd/system/docker.service.d/
cat /etc/systemd/system/docker.service.d/docker-dns.conf
  1. 备份并禁用有问题的 DNS 配置:
# 备份现有配置
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 服务:
sudo systemctl daemon-reload
sudo systemctl restart docker
  1. 重新启动应用服务:
docker compose --env-file .env --env-file .env.image.amd64 up -d

验证解决方案

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

  1. 检查容器状态:
docker ps
  1. 测试 DNS 解析:
docker run --rm --network wanwu-net alpine:latest nslookup redis-wanwu
  1. 查看服务日志:
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 配置,我们成功解决了服务间的网络通信问题,所有微服务都能正常启动并相互通信。

posted @ 2026-01-11 13:28  牛奔  阅读(12)  评论(0)    收藏  举报