启动程序时,如果出现以下报错:
Address already in use
或者Docker提示:
port is already allocated
通常说明程序尝试使用的地址和端口发生了冲突。
处理前应先查清楚是谁占用了端口,以及这个服务是否仍在使用。下面以8080端口为例,实际操作时请替换为报错中的端口。
一、查询端口占用情况
检查TCP监听端口:
sudo ss -ltnp 'sport = :8080'
如果报错涉及UDP,则执行:
sudo ss -lunp 'sport = :8080'
参数含义如下:
| 参数 | 作用 |
|---|---|
-l |
查看监听或等待接收的套接字 |
-t |
查看TCP |
-u |
查看UDP |
-n |
使用数字显示地址和端口 |
-p |
显示关联进程信息 |
可能看到类似结果:
LISTEN 0 511 127.0.0.1:8080 0.0.0.0:*
users:(("node",pid=2468,fd=7))
这个示例表示:PID为2468的Node.js进程正在监听TCP 8080端口。
需要同时关注监听地址:
-
127.0.0.1:8080:监听IPv4回环地址。 -
0.0.0.0:8080:监听所有本地IPv4地址。 -
[::]:8080:监听IPv6通配地址;是否同时接收IPv4连接,取决于套接字设置。
TCP和UDP需要分别检查。 UDP 8080被占用,并不等于TCP 8080也被占用。

二、确认进程属于哪个程序或服务
查到PID后,查看程序路径、启动参数和运行用户:
ps -p 2468 -o pid,ppid,user,args
2468是示例PID,需要替换成查询到的实际值。
如果服务器使用systemd管理服务,还可以执行:
sudo systemctl status 2468 --no-pager
该命令可以帮助查看进程所属的systemd单元。例如:
demo-api.service - Demo API
Active: active (running)
Main PID: 2468 (node)
接下来应确认:
-
这是不是已经正常运行的业务。
-
是否重复执行了启动命令。
-
是否有面板、systemd、Supervisor或PM2负责管理它。
-
新启动的程序是否本来就应该使用另一个端口。
返回的单元也可能是登录会话等其他类型,不能看到单元名称就直接停止,需要结合程序路径和业务用途判断。

三、Docker部署还要检查端口映射
如果服务器运行了Docker,查看容器及其端口映射:
docker ps --format 'table {{.Names}}\t{{.Ports}}'
例如下面这种映射:
127.0.0.1:8080->80/tcp
表示宿主机的TCP 8080端口映射到了容器内的80端口。
排查时要区分:
| 位置 | 示例 | 含义 |
|---|---|---|
| 宿主机端口 | 8080 | 外部客户端或反向代理访问的端口 |
| 容器端口 | 80 | 应用在容器内部监听的端口 |
两个使用独立网络命名空间的容器,可以各自在内部监听80端口;但发布到宿主机时,不能随意使用相同且冲突的宿主机地址和端口。
Docker端口发布可能通过转发规则实现,因此不能仅凭ss中没有看到docker-proxy,就认定没有容器占用该端口。还应核对容器端口映射。
如果容器使用network_mode: host,则直接共享宿主机网络,需要按宿主机端口冲突处理。
四、选择停止重复实例或修改端口
确认占用来源后,根据业务情况选择处理方式。
情况一:原来的服务仍然需要运行
保留原服务,为新应用选择其他未冲突的端口,例如8081。
随后同步调整访问地址、反向代理、健康检查及其他调用方配置。
情况二:确实是可以停止的旧服务
如果已经确认demo-api.service是可以停止的旧实例,可以执行:
sudo systemctl stop demo-api.service
服务名必须替换为实际名称。停止后,再次查询8080端口,确认是否释放。
如果程序由Docker、面板、Supervisor或PM2管理,应通过对应管理工具停止,避免直接结束子进程后又被自动启动。
某些服务由systemd套接字激活,可以先检查:
sudo systemctl list-sockets --all --no-pager
存在相关.socket单元时,仅停止业务进程或.service,可能无法释放监听端口,需要核对对应套接字单元。
不要在未确认用途的情况下,直接批量强制结束占用端口的进程。
五、示例:修改Docker Compose宿主机端口
假设已有一个Compose服务叫web,容器内部监听80端口,准备将宿主机端口从8080改为8081。
先按第1节检查8081,并核对现有Docker映射,然后修改现有配置中的ports:
services:
web:
# 保留现有 image、volumes、environment 等配置
ports:
- "127.0.0.1:8081:80"
这是配置节选,不能直接覆盖完整的Compose文件。
本例绑定宿主机回环地址,适合由宿主机上的反向代理访问。需要公网直连时,应按实际部署要求选择绑定地址并配置访问控制。
修改完成后,在该Compose项目目录中执行:
docker compose config -q && docker compose up -d web
web是示例服务名,需要替换成实际名称。使用多个配置文件或自定义项目名的部署,应沿用原来的启动参数。
端口映射变化会涉及容器重建。执行前确认业务数据已通过数据卷或绑定目录持久化,并安排好可能出现的短暂中断。
只执行docker compose restart不会应用修改后的端口映射。
查看最终映射:
docker compose port web 80
本例预期输出:
127.0.0.1:8081
容器内应用仍监听80端口,宿主机访问端口已经改为8081。

六、验证服务启动及访问结果
对于普通宿主机服务,可以再次检查监听情况:
sudo ss -ltnp 'sport = :8081'
核对监听地址、端口和进程是否符合预期。
对于Docker服务,应结合容器状态、端口映射和应用日志确认结果。
如果是HTTP应用,可以在宿主机上测试:
curl -i --max-time 10 http://127.0.0.1:8081/
路径和协议应按实际应用调整。HTTPS服务或其他协议,应使用相应的地址和客户端测试。
最后确认:
-
服务不再出现端口绑定失败。
-
实际页面或业务接口能够正常使用。
-
反向代理和监控已使用正确端口。
-
由原来的服务管理方式启动时,不会再次产生重复实例。
端口成功监听,只能说明绑定成功,还需要验证业务结果。
常见问题
1. 为什么结束进程后,端口马上又被占用了?
程序可能受到systemd、Docker重启策略、Supervisor或PM2管理。应先确认管理来源,再通过对应工具停止或修改配置。
2. ss没有查到监听,为什么仍然报端口被占用?
需要核对TCP或UDP、IPv4或IPv6,以及命令执行的位置是否与应用处于同一网络命名空间。Docker部署还应检查宿主机端口映射。
也可能是程序启动过程中重复绑定同一地址和端口,需要查看完整启动日志。
3. 放行防火墙端口,能解决端口被占用吗?
不能。端口占用属于本地地址绑定冲突,防火墙放行主要影响流量是否能够通过,两者是不同问题。
注意事项
修改前备份相关配置,先确认占用进程的业务用途。不要通过重启整台服务器代替定位,也不要直接停止数据库、SSH或正在提供服务的程序。
如果使用莱卡云服务器后仍无法定位问题,可提交工单,提供完整报错、端口号、TCP或UDP协议、进程查询结果及部署方式,便于进一步排查。分享启动参数和日志前,请隐藏密码、令牌等敏感信息。