从 deploy/ 目录执行以下命令:
docker compose -f compose.yaml ps
docker compose -f compose.yaml logs -f web monitor
EISDIR: illegal operation on a directory, read配置路径指向目录,不是 YAML 文件。检查:
ls -ld ../config ../config/server.yaml
file ../config/server.yaml
../config/server.yaml 必须显示为普通文本文件。如果它被误创建成目录:
rm -rf ../config/server.yaml
cp ../config/server.example.yaml ../config/server.yaml
然后填写配置并重建:
docker compose -f compose.yaml up -d --force-recreate
错误类似:
Could not find a production build in the '.next' directory
说明正在运行旧镜像或 Dockerfile 的 Web 工作目录不正确。等待 GitHub Actions 发布包含当前 Dockerfile 的镜像后:
docker compose -f compose.yaml pull
docker compose -f compose.yaml up -d --force-recreate
确认实际 digest:
docker image inspect ghcr.io/<owner>/minecraft-server-status-web:main --format ''
先看日志:
docker compose -f compose.yaml logs --tail=100 monitor
检查项:
server.yaml 可读取,且启用了至少一个入口。${JAVA_SERVER_HOST} / ${BEDROCK_SERVER_HOST} 若被使用,容器环境中必须存在;最简单的方法是直接在配置里填写主机名。正常轮次会输出:
{"event":"monitor.check.complete", ...}
UNKNOWN 表示无快照,或最后检查时间超过 staleAfterIntervals × intervalSeconds。
curl -fsS http://127.0.0.1:15879/api/v1/status
检查 checkedAt、Monitor 容器运行状态和日志。/api/health/ready 仅证明 SQLite 可读,不能证明 Monitor 仍在运行。
等待连续失败达到 downAfterFailures(默认 3)后才会显示离线。恢复也需要连续成功达到 upAfterSuccesses(默认 2)。
页面上的手动检查仅是临时结果:Java 使用与 Monitor 相同的 Java Server List Ping,基岩为 UDP ping;它不会改变历史或状态机。
手动检查的浏览器 Origin 必须与 Web 容器的 APP_BASE_URL 一致。当前 Compose 使用:
APP_BASE_URL=https://status.windking.fans
确认浏览器实际访问的域名与其一致;若使用别名域名,在 Web 容器添加 PROBE_ALLOWED_ORIGINS=https://别名域名。反向代理可将请求转发到 127.0.0.1:15879,但不应改写浏览器的公开 Origin。
浏览器开发者工具中查看 POST /api/v1/probe 的 HTTP 状态、JSON 响应和 X-Request-ID。再用请求 ID 查询:
docker compose -f compose.yaml logs --tail=200 web
403:公开 Origin 配置不匹配、缺失或请求不是浏览器同源请求。429:同一 scope 20 秒内重复检查。503:Web 无法读取配置或执行检查;查看 Web 日志。200 且 success: false:HTTP 路由和来源授权均正常,但 Web 容器未能完成与目标的协议检查。先确认 Web 与 Monitor 使用同一镜像版本、相同的 /config/server.yaml 挂载;再在两个容器中对配置里的实际 Java 主机和端口分别运行:
docker compose -f compose.yaml exec web node -e "require('dns').lookup('<Java主机>', { all: true }, console.log)"
docker compose -f compose.yaml exec monitor node -e "require('dns').lookup('<Java主机>', { all: true }, console.log)"
docker compose -f compose.yaml exec web node -e "const net=require('net');const s=net.connect({host:'<Java主机>',port:<端口>});s.setTimeout(5000);s.on('connect',()=>{console.log('connected');s.destroy()});s.on('timeout',()=>{console.log('timeout');s.destroy()});s.on('error',e=>console.log(e.code,e.message))"
比较 DNS 返回的 IPv4/IPv6 地址,并检查 Docker/宿主机出站防火墙与目标端口。基岩版需要单独确认 UDP/RakNet 出站路径。
如果代理运行在宿主机,应代理到:
http://127.0.0.1:15879
如果需要只允许宿主机反向代理访问,可将 Compose 映射改为:
ports:
- "127.0.0.1:15879:3000"
不要在宿主机代理配置中使用 web:3000;该名称仅对同一 Docker 网络中的容器可解析。
../data/status.db,确认该目录没有被清空。retentionDays(默认 90 天)会清理。