VS Code远程Docker容器连接随机卡顿5秒故障排查
Docker容器跨服务访问5秒固定卡顿排查方案
三个容器均稳定运行无重启的前提下,该类固定5秒的随机卡顿属于Docker网络层经典故障,和数据库、Redis服务本身无关,按以下步骤定位修复:
故障定位步骤
- 首先验证DNS解析超时问题(该类故障90%以上为该原因):
进入app容器,循环测试服务名解析耗时,复现卡顿场景:
若某几次解析耗时恰好稳定在5秒左右,即可确认是Docker内置DNS服务(127.0.0.11)转发超时导致。单次telnet测试未复现属于概率触发的正常现象,样本量不足无法复现。# 进入app容器,替换为实际的app容器名称 docker exec -it <app容器名> sh # 循环执行50次解析,统计耗时 for i in {1..50}; do time getent hosts db; sleep 1; done - 若DNS解析无异常,排查conntrack表丢包问题:
在宿主机执行以下命令,查看连接跟踪表是否存在溢出丢包:
若drop计数大于0,或当前表项数接近最大值,即为conntrack表满丢包,TCP重传超时恰好为5秒,触发卡顿。# 查看conntrack丢包计数 conntrack -S | grep -E 'drop|insert_failed' # 查看当前conntrack表项数、表最大值 sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
修复方案
针对DNS解析超时问题
- 调整Docker daemon配置,关闭性能较差的用户态代理,缩短DNS超时时间:
编辑宿主机/etc/docker/daemon.json(不存在则新建),写入以下配置:
执行{ "userland-proxy": false, "dns": ["114.114.114.114", "223.5.5.5"], "dns-opts": ["timeout:1", "attempts:1"] }systemctl restart docker重启Docker服务生效,注意重启会停止所有运行中容器,提前安排业务停机。
如果使用Mac/Windows版本Docker Desktop,直接升级到最新稳定版即可,老版本Desktop内置DNS转发存在固定5秒超时的已知bug。 - 配置静态hosts映射绕开Docker DNS解析,一劳永逸规避该问题:
先在宿主机执行命令查询db、rd容器的固定IP:
在docker-compose.yml的app服务配置中添加docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <db容器名> docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <rd容器名>extra_hosts字段,写死IP映射:
执行services: app: # 保留原有depends_on、build、volumes、command配置 extra_hosts: - "db:<上一步查询到的db容器IP>" - "rd:<上一步查询到的rd容器IP>"docker-compose up -d重建app容器生效,后续访问db、rd直接走hosts解析,不经过Docker DNS。 - 业务侧配置连接池保活策略:给PostgreSQL、Redis连接池开启TCP keepalive,配置空闲连接每30秒做一次可用性检测,自动剔除失效连接,避免业务请求拿到半开连接触发卡顿。
针对conntrack表溢出问题
调整宿主机内核参数,扩大conntrack表容量,优化超时时间:
编辑/etc/sysctl.conf,写入以下配置:
# conntrack表最大容量调整为100万 net.netfilter.nf_conntrack_max = 1048576 # TCP连接跟踪表项超时调整为300秒,小于数据库、Redis默认空闲连接超时 net.netfilter.nf_conntrack_tcp_timeout_established = 300 # 开启TCP保活,缩短保活探测间隔 net.ipv4.tcp_keepalive_time = 120 net.ipv4.tcp_keepalive_intvl = 30 net.ipv4.tcp_keepalive_probes = 3
执行sysctl -p加载配置生效。
配置优化建议
现有docker-compose.yml未显式声明网络,默认使用compose自动创建的bridge网络,建议显式声明自定义bridge网络,提升网络转发和DNS稳定性:
# 保留原有services、volumes配置 networks: default: driver: bridge driver_opts: com.docker.network.bridge.enable_icc: "true"
修改后执行docker-compose up -d重建网络生效。
内容的提问来源于stack exchange,提问作者David Dahan
相关产品推荐
相关产品推荐

