CentOS 7.9 上一台机器先跑着宿主机自带的 Java 服务占着 8080,再用 docker run -p 8080:80 起 nginx,命令没有报错,访问 8080 一直是 Java 那个页面。

把日志和配置对完,能解释这个现象的基本就这几处。docker 默认只监听 IPv4 的 0.0.0.0,宿主机进程先占了同一个端口,内核把连接给了先绑定的一方;端口绑定失败时 docker 只把告警写进 daemon 日志,容器照样显示 Up;docker-proxy 只负责转发,绑定不上时不阻断容器启动;IPv6 与 IPv4 是两套绑定,ss 里看着端口在听,其实对端不是同一个进程。

动手时先看端口到底被哪个进程占着

ss -lntp 'sport = :8080'

接着查 docker 启动时的端口绑定告警

journalctl -u docker --since '10 min ago' | grep -i 'port is already'

随后换一个未被占用的宿主端口重启容器

docker run -d --name web -p 8081:80 nginx:1.25

从本机验证映射是否真的生效

curl -sI http://127.0.0.1:8081 | head -3

恢复的判定其实很直接。ss 里 8081 的持有进程是 docker-proxy,curl 返回 nginx 的 Server 头,容器日志中出现正常的访问记录。

提醒一点。docker 不会因为端口冲突拒绝启动容器,只会悄悄不转发;上线前用 ss 核一遍宿主机端口,比事后翻 daemon 日志省事。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。

作者 9823189