报错从哪里来
docker run 发布端口时,如果宿主端口已被占用,会报 bind: address already in use,也可能出现 userland proxy 相关的报错。占用方通常是另一个发布了同一宿主端口的容器,或者是宿主上直接监听的进程。排查的目标始终是宿主端口这一侧的占用者,而不是容器内部的端口。
基本信息
| 报错形态 | bind: address already in use / userland proxy listen 失败 |
|---|---|
| 排查方向 | 容器端口映射与宿主进程(含 docker-proxy) |
| 处置方式 | 改映射端口或停掉占用方 |
| 常见冲突端口 | 80、443、8080、3306 |
| 适用平台 | Docker Engine(Linux 宿主) |
典型使用场景
- 新版本容器启动失败,旧容器仍在占用同一宿主端口
- 宿主上装了 nginx 或数据库,与容器的映射端口撞车
- CI 并行任务抢占同一宿主端口
- 排查「昨天还能起、今天起不来」的端口变化
- 迁移前先确认目标宿主端口是否空闲
定位与处置
定位与处置
docker ps -a --format '{{.Names}} {{.Ports}}' | grep 8080 # 哪个容器发布了该端口
ss -ltnp | grep 8080 # 宿主上谁在监听
sudo lsof -i :8080 # 进一步确认进程
docker run -d -p 8081:80 --name web nginx:1.27 # 改用空闲宿主端口
curl -sI localhost:8081 | head -1 # 验证新映射可用现象与处置
| 现象 | 含义 | 处置 |
|---|---|---|
| bind: address already in use | 宿主端口被占用 | 停掉占用方或改宿主端口 |
| userland proxy listen 报错 | Docker 转发进程起不来 | 先看残留的转发进程与容器状态 |
| 端口开着但访问报错 | 映射方向写反或应用未监听 | 按宿主:容器顺序核对 |
| host 网络下映射无效 | host 模式忽略发布参数 | 直接排查宿主端口占用 |
docker-proxy 是 Docker 自己的端口转发进程,停掉它会破坏对应容器的端口发布,排查时不要顺手清理它。
同一宿主上两个容器各自发布不同的宿主端口不会冲突,冲突永远发生在宿主端口这一侧。
减少冲突的做法
- 给每个服务分配固定且不重复的宿主端口段,写进运维文档
- 内部服务不发布端口,交给同网络的反向代理访问
- CI 里用随机端口或每次运行前先探测端口占用
- 排查时先看容器映射清单,再看宿主监听进程,顺序反了容易漏