谁能想到,一个下划线 _ 竟让我的 Docker 容器“失联”了?
在程序员的世界里,有些 Bug 像恶魔,烧脑费钱;而有些 Bug 像初恋,单纯是因为你“不了解它的脾气”。
最近我在部署一套基于 若依 (RuoYi) 的微服务系统时,遇到了一个让我怀疑人生的 400 错误。明明网络通了,容器名也能 Ping 通,可请求就是发不过去。折腾了一圈发现,罪魁祸首竟然是随手打下的那个下划线 _(前人之坑)。
今天,我就把这个价值几根头发的“坑”给填平了,分享给大家。
一、 案发现场:我那“完美”的 Docker 布局
场景是这样的:我有两个容器,一个是 Nginx(负责转发),一个是网关服务(基于 Spring Cloud Gateway 的若依管理端)。
为了显得整齐划一,我给管理端容器起名叫:zhinengbi_manage。
在 Nginx 的配置文件里,我自信地写下:
location /admin-sys/ {
proxy_pass http://zhinengbi_manage:8888/; # 看起来逻辑满分,对吧?
}
当我满怀期待地启动容器,执行 curl -I http://zhinengbi_manage:8888 时,现实给了我一记响亮的耳光:
HTTP/1.1 400 Bad Request
二、 破案过程:为什么 Ping 得通,Curl 不通?
我当时的第一反应是:网络没通? 于是我进入容器内部 ping zhinengbi_manage,结果:通了! Docker 内部 DNS 解析完全正常。
奇了怪了,网络既然通了,为什么 Web 服务器不待见我?
经过一番彻夜排查(并求助了 RFC 文档),我终于找到了原因:HTTP Host 头部规范。
域名规范(RFC 1035):在标准的域名规范中,主机名只能包含字母、数字和连字符 -。下划线 _ 是非法的。
Web 服务器的严谨性:虽然 Docker 允许你用下划线给容器命名,但像 Nginx、Tomcat、Netty(Spring Cloud Gateway 底层通常是 Netty)这些严谨的 Web 服务器,在处理 HTTP 请求头里的 Host 字段时,如果发现域名里有下划线,会认为这是一个非法的畸形请求。
结果:它们为了安全,直接拒绝服务,反手回你一个 400 Bad Request。
三、 填坑指南:如何优雅地修正?
既然找到了病根,药方也就出来了:去“划”改“横”。
- 修改 Docker Compose 配置文件
把所有的 _ 全部换成 -。这不仅是为了兼容性,更是为了符合生产环境的命名规范。
services:
zhinengbi-manage: # 以前是 zhinengbi_manage
image: zhinengbi-manage:1.0
container_name: zhinengbi-manage
# ... 其他配置
- 同步更新 Nginx 配置
因为 Nginx 是通过服务名来寻找容器的,所以 nginx.conf 里的 proxy_pass 也得改:
location /admin-sys/ {
# 告别下划线,拥抱连字符
proxy_pass http://zhinengbi-manage:8888/;
}
- 别忘了配置持久化
为了以后修改配置不再重新构建镜像,强烈建议把 Nginx 的配置文件挂载出来:
volumes:
- ./conf/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
四、 总结:避坑金句
这次踩坑让我总结了几条血泪教训,建议背诵:
命名千万条,规范第一条。 无论是 Docker 容器名、K8s 服务名还是数据库名,能用 -(连字符)就别用 _(下划线)。
能 Ping 通不代表能 Curl 通。 Ping 是 ICMP 协议,只管地址解析;Curl 是 HTTP 协议,它对“仪容仪表”(Header 规范)要求很高。
配置要挂载,改名才不快。 永远记得把配置文件挂载到宿主机,否则改一个字母你都要重装整个世界。
看完这篇,赶紧检查一下你的 Docker 容器名,别让那个小小的下划线成了你加班的导火索!
更多推荐

所有评论(0)