--- title: 端口冲突检查的实现方式(deploy.py / manage.py reconfigure) type: decision permalink: main/projects/d1932ed6-07d3-4463-a224-8534ffd69a07/端口冲突检查的实现方式-deploy.py-manage.py-reconfigure stable_id: 68deebdd-e5d1-4bc6-8e70-e4342e72f986 scope: project project_id: d1932ed6-07d3-4463-a224-8534ffd69a07 memory_type: decision status: active revision: 1 restored_from_commit: 6a6a895eafcca6052e81a14fca103a42635dd1c2 created_at: '2026-09-23T15:05:44.159044+00:00' updated_at: '2026-09-23T15:05:44.159107+00:00' tags: - nextoffice - deploy - ports - conflict-check - manage.py --- 背景:用户要求安装时可自定义 Nextcloud/ONLYOFFICE 宿主机端口,并检查端口是否冲突或被占用(部分服务器 8080/8081 已被其他系统使用)。自定义端口能力此前已存在(交互提示 + --nextcloud-port/--onlyoffice-port),本次补齐占用检查。 决定与实现(提交 7b3796e): - 端口检测放在 deploy.py:`docker_published_ports()` 解析 `docker ps --format '{{.Names}}\t{{.Label "com.docker.compose.project"}}\t{{.Ports}}'`,用正则 `:(\d+)(?:-(\d+))?->\d+(?:-\d+)?/tcp` 取已发布 TCP 端口(支持端口区间,忽略 UDP);`port_holder()` 先查 Docker 发布端口,再对 0.0.0.0:port 做 bind 探测。 - 本项目容器(compose 项目名 `nextoffice`,常量 COMPOSE_PROJECT 必须与 docker-compose.yml 的 name 一致)占用的端口视为可用,保证在已部署服务器上重复运行 deploy.py / reconfigure 不误报。 - bind 遇 PermissionError(非 root 绑定特权端口)视为无法验证、放行由 Docker 决定;其他 OSError 视为“本机其他程序”占用。 - `choose_port(value, label, default, reserved)` 统一处理 CLI 值和交互输入:CLI 值被占用/越界/非数字/与另一服务相同时抛 InstallError 直接退出,不写 .env;交互模式默认端口被占用时向上扫描最多 200 个端口建议第一个可用端口,输入无效则重新提示。 - 已有 .env 重跑 deploy.py 时,`check_configured_ports()` 在拉镜像前预检两个端口是否被外部占用,并提示用 `manage.py reconfigure --nextcloud-port/--onlyoffice-port` 更换。 - manage.py 通过 `from deploy import choose_port` 复用逻辑(两个脚本同目录交付,不新增共享模块);reconfigure 的端口输入因此也有范围/占用/相同校验。 - 不使用 SO_REUSEADDR 做探测(Windows 上会允许抢占端口)。 - AGENT.md 按用户要求加入 .gitignore,不提交。docs/ 目录仍被 .gitignore 忽略,docs/INSTALL.md、docs/TROUBLESHOOTING.md 的端口说明只存在于本地交付目录。