DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

Docker 已发布端口仍连不上:nREPL 监听在容器回环地址

nREPL 只监听容器回环时,已有 Docker 端口发布仍无法到达。调整应用 bind,并把宿主机入口限制到本地或受控 SSH 隧道。

Compose 显示 0.0.0.0:2001->54654/tcp,宿主机 nREPL 客户端仍连不上,容器内访问却正常。对默认绑定 127.0.0.1 的 nREPL 服务,先检查应用的监听地址:发布端口通常转发到容器的网络 IP,无法让只监听容器回环地址的服务接受这条连接。

本文针对普通 Docker 桥接网络中的 nREPL。它是可以执行代码的调试入口,修改监听时要同时控制宿主机发布范围;不能为连通性把远程执行入口直接开放到公网。

区分三个地址所在的位置

在容器里,127.0.0.1:54654 是该容器自己的回环;容器的桥接网络 IP 是另一个地址。宿主机上的 127.0.0.1:2001 则是宿主机的发布入口。即使容器运行在同一台电脑上,这三个位置也不能互换。

先用实际服务名查看当前运行状态:

docker compose ps
docker compose logs --tail=100 app
docker compose config

app 是示例服务名。启动用了多个文件、项目名或环境文件时,检查也要带相同参数。config 可能输出展开后的凭据,只在受控环境查看。

核对映射右侧端口与 nREPL 实际端口一致,并从启动日志、启动参数或应用配置确认 bind 地址。nREPL 命令行默认 bind 是 127.0.0.1;未指定端口还可能使用随机端口。嵌入式服务器、Leiningen 或其他工具包装的入口,应检查它们实际传给 nREPL 的设置,而不是假定都按同一个配置文件启动。

若没有发布映射,先处理宿主机入口;若服务没启动或端口不同,先修正实际启动配置。只有端口一致、映射存在,且监听只限容器回环时,才沿下面的 bind 路径处理。

应用监听容器网络,宿主机入口保留在回环

nREPL 命令行入口支持以下参数片段,不能把它当成任意 Java 应用都接受的 JVM 参数:

--bind 0.0.0.0 --port 54654

应在现有 nREPL 启动方式中设置它们。嵌入式 nREPL 使用应用对应的启动配置,让它监听容器网络可达的地址。0.0.0.0 表示容器内所有 IPv4 接口,不是客户端应当连接的目标地址。

需要只让宿主机或 SSH 隧道访问时,在既有服务中限制发布入口:

ports:
  - "127.0.0.1:2001:54654"

这与“应用仍只监听容器 127.0.0.1”不同:应用接受来自容器网络的转发,宿主机发布仅绑定自己的回环地址。容器网络上的其他可达容器仍可能访问应用,因此还要控制网络成员、调试入口权限及所用传输保护。

Docker Engine 28.0.0 以前,发布到 localhost 的端口存在同一二层网段其他主机可达的边界问题。旧环境不能仅用这项映射保证隔离;按受支持版本和实际网络策略管理访问,保留必要的认证与主机访问控制。

远程调试可先建立经过认证的 SSH 本地转发,让远端连接目标为服务器的 127.0.0.1:2001,再由本地 nREPL 客户端连接隧道入口。SSH 转发是否允许及身份权限,需要由服务器策略控制;这不要求把 nREPL 端口直接发布到外部接口。

用实际协议判断是否连通

telnet 显示“Connected”后立刻断开,或 curl 没有返回网页,都不足以判断 nREPL 可用。TCP 接受、转发和应用协议是不同阶段,nREPL 也不是普通 HTTP 服务。

使用与服务器传输方式和版本相容的 nREPL 客户端,连接正确的宿主机或隧道端口。若 TCP 已到达、客户端仍报协议或认证错误,检查 bencode、TLS 或应用中间件配置,不能继续把问题全部归因于 Docker 映射。

改 bind、固定端口和发布地址前保存原启动配置,确认调试入口的业务影响与数据持久化。更新通常要重启或重建相关容器,会终止调试会话;保留原镜像、参数和挂载即可回退,不需要删卷或关闭应用保护。

验收时确认客户端完成预期协议连接和授权,应用仍正常工作,访问范围符合原定要求。既要验证允许的宿主机或隧道路径,也要核对未经授权的外部入口没有因改监听而开放。回退会断开新会话,但不能撤销调试期间已经执行的代码或数据修改。