Administrator
Administrator
发布于 2026-10-28 / 0 阅读
0
0

Docker 故障排查(05):port is already allocated:容器端口冲突该查谁

适用:使用 systemd 的 Linux 服务器、常规 rootful Docker Engine;Compose 示例使用 docker compose V2。本文为教学故障场景,错误文本和结果为示意,具体输出以现场为准。

一、遭遇情况:镜像没变,新容器却启动失败

服务器原来运行一套 Web 服务,再部署第二套时出现:

Bind for 0.0.0.0:8080 failed: port is already allocated

另一些环境可能显示 address already in use。这通常表示 Docker 无法占用指定的宿主机地址与端口,不等于 Nginx 镜像坏了,也不表示两个容器内部都不能使用 80。

本篇案例是两套服务都写了 8080:80,争用宿主机的 8080。目标是找到冲突双方,再决定改端口还是调整已有服务。

二、原因分析:冒号两边属于不同网络空间

-p 8080:80 的左侧是宿主机端口,右侧是容器端口。两个不同容器内部都监听 80,通常没有问题;但它们不能同时占用同一个宿主机地址、同一个 TCP 端口。

宿主机端口冲突的定位与修复

端口冲突也可能来自宿主机直接运行的 Nginx、旧 Compose 项目,或绑定所有地址的其他进程。TCP 与 UDP 要分别检查,IPv4 与 IPv6 的绑定关系也可能影响判断。

三、排查思路:把“谁占用”找出来

1. 查看现有容器及其发布端口

docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
docker ps -a --filter publish=8080
sudo ss -lntp '( sport = :8080 )'

ss 帮助识别宿主机监听进程;Docker 的端口映射还可能由网络规则实现,因此不能因为 ss 没显示普通监听进程,就断定 Docker 没有占用端口。要与容器发布信息一起判断。

不要看到一个 PID 就直接 kill -9。先确认服务名称、所属部署和业务用途,避免把正常服务当作“残留进程”。

2. 检查失败容器到底执行到哪一步

假设失败容器名为 web-new:

docker inspect web-new --format 'Status={{.State.Status}} Error={{.State.Error}}'
docker inspect web-new --format '{{json .HostConfig.PortBindings}}'

若容器在网络初始化阶段就失败,应用可能根本没运行,docker logs web-new 没输出也正常。此时改应用配置、查 Nginx 错误日志往往跑偏。

四、实践:用两个独立实验容器复现

以下仅在空闲练习端口执行。镜像需要能拉取,实验名称必须未被占用:

docker run -d --name dt05-web-a -p 127.0.0.1:18080:80 nginx:stable-alpine
docker run -d --name dt05-web-b -p 127.0.0.1:18080:80 nginx:stable-alpine

第二条预期因同一发布端口冲突而失败。随后检查:

docker ps -a --filter name=dt05-web
docker inspect dt05-web-b --format '{{.State.Error}}'
curl -I --max-time 5 http://127.0.0.1:18080

A 应仍能提供服务。端口冲突不会自动把原服务替换成新服务。

在确认 B 是刚才新建、从未承载业务的失败实验容器后,删除它并换一个空闲端口重建:

docker rm dt05-web-b
docker run -d --name dt05-web-b -p 127.0.0.1:18081:80 nginx:stable-alpine
curl -I --max-time 5 http://127.0.0.1:18080
curl -I --max-time 5 http://127.0.0.1:18081

两个请求都应得到 HTTP 响应。实验结束后可以停止并删除这两个明确的实验容器,不要用批量删除所有容器的命令清场。

五、生产修复要考虑哪些关联

若第二套服务原本就应该使用独立端口,应修改部署配置并重建相应容器,同时同步反向代理、健康检查和访问文档。对已有容器执行 docker restart,不会把原来的端口映射变成新的映射。

若旧容器确实应该下线,先确认流量切换、数据卷和回退方式,再停止旧服务。不要把“端口腾出来了”当作新服务已正常处理请求的证据。

使用 Compose 时,可先 docker compose config 查看解析后的端口配置,确认不是环境变量默认值让两套项目都落到同一个端口。修改后 docker compose up -d 服务名,观察是否重建了目标容器。

六、验证与总结

修复后分别检查发布端口、应用 HTTP 响应、代理上游地址,以及旧服务是否仍按计划运行。没有必要通过重启整台 Docker 服务解决一个明确的单端口冲突。

判断路径是:看错误中的宿主机端口 → 找实际占用者 → 确认部署意图 → 调整一处入口 → 验证两侧业务。容器内部的 80 可以重复,宿主机同一入口不能随意重复。

参考资料


上一篇 · 系列目录 · 下一篇


评论