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 配置,我们成功解决了服务间的网络通信问题,所有微服务都能正常启动并相互通信。

相关推荐
OpsEye2 小时前
监控 100 问(三):监控告警触发后如何快速定位与解决问题
运维·网络·it运维·it·监控·监控系统
线束线缆组件品替网2 小时前
Conxall 防水线缆在户外工控中的布线实践
运维·人工智能·汽车·电脑·材料工程·智能电视
济6172 小时前
linux(第十四期)--官方 SDK 移植实验-- Ubuntu20.04
linux·运维·服务器
范纹杉想快点毕业2 小时前
欧几里得算法与扩展欧几里得算法,C语言编程实现(零基础全解析)
运维·c语言·单片机·嵌入式硬件·算法
小猪佩奇TONY2 小时前
Linux 内核学习(16) --- linux x86-64 虚拟地址空间和区域
linux·运维·学习
L1624762 小时前
Docker 安装部署全流程使用指南(Linux 通用版)
linux·docker·容器
杰克崔3 小时前
kprobe及kretprobe的基于例子来调试分析其原理
linux·运维·服务器·车载系统
Mr. Cao code3 小时前
MySQL数据卷实战:持久化存储秘籍
数据库·mysql·docker·容器
小北方城市网3 小时前
微服务架构设计实战指南:从拆分到落地,构建高可用分布式系统
java·运维·数据库·分布式·python·微服务