diff --git a/backend/data/logs/node-access.log b/backend/data/logs/node-access.log index 6301383..1d011db 100644 --- a/backend/data/logs/node-access.log +++ b/backend/data/logs/node-access.log @@ -5617,3 +5617,4 @@ ::1 - - [15/Mar/2026:09:15:19 +0000] "GET /api/push-groups?key=HBpEnbtj9BJZ HTTP/1.1" 304 - "http://localhost:3000/manage.html?key=HBpEnbtj9BJZ" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36" ::1 - - [15/Mar/2026:09:15:28 +0000] "GET /api/ws-status HTTP/1.1" 200 19 "http://localhost:3000/manage.html?key=HBpEnbtj9BJZ" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36" [2026-03-15T09:31:04.748Z] Static frontend server listening on port 3000; access log: /Users/dannier/Desktop/living/AICLW/wechatAiclaw/backend/data/logs/node-access.log +[2026-03-15T09:48:21.689Z] Static frontend server listening on port 3000; access log: /Users/dannier/Desktop/living/AICLW/wechatAiclaw/backend/data/logs/node-access.log diff --git a/docs/nginx-example.conf b/docs/nginx-example.conf new file mode 100644 index 0000000..0aa9c0b --- /dev/null +++ b/docs/nginx-example.conf @@ -0,0 +1,48 @@ +# Nginx 反向代理示例(前置到 Docker 容器) +# 502 Bad Gateway 通常表示 nginx 连不上上游,请按下方排查。 +# +# 常见原因: +# 1. proxy_pass 的端口与宿主机映射不一致:run-docker.sh 默认 -p 3003:3000 -p 8008:8000, +# 则宿主机上前端是 3003、后端是 8008;若用 -p 3000:3000,则前端是 3000。 +# 2. 上游写成了容器内端口:若 nginx 与 Docker 在同一台机,应写 127.0.0.1:宿主机端口(如 3003), +# 不要写 127.0.0.1:3000(除非宿主机映射就是 3000:3000)。 +# 3. 容器或容器内进程未启动:docker logs wechat-admin-backend 查看是否有报错。 +# 4. 防火墙或安全组未放行宿主机端口。 + +# 假设宿主机映射为:前端 3003、后端 8008(与 run-docker.sh 默认一致) +upstream wechat_frontend { + server 127.0.0.1:3003; + keepalive 32; +} + +upstream wechat_backend { + server 127.0.0.1:8008; + keepalive 32; +} + +server { + listen 80; + server_name your-domain.com; + + # 前端静态 + Node 代理 + location / { + proxy_pass http://wechat_frontend; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Connection ""; + } + + # 后端 API(可选:若希望 /api 直接打到后端可单独配置) + location /api/ { + proxy_pass http://wechat_backend/api/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Connection ""; + } +} diff --git a/run-docker.sh b/run-docker.sh index d3a7fe5..f38d3af 100755 --- a/run-docker.sh +++ b/run-docker.sh @@ -5,7 +5,6 @@ # -p, --port PORT 前端宿主机端口,默认 3000 # -b, --backend-port PORT 后端 API 宿主机端口,默认 8000(容器内固定 8000) # -d, --data-dir DIR 数据目录挂载,默认 ./data -cp .env.prod.example .env.prod set -e IMAGE_NAME="wechat-admin-backend" @@ -62,11 +61,26 @@ echo "Running container ${CONTAINER_NAME} (frontend :${PORT}, backend :${BACKEND docker run -d \ --name "${CONTAINER_NAME}" \ --env-file "${ENV_FILE}" \ + -e "HOST=0.0.0.0" \ + -e "PORT=3000" \ + -e "BACKEND_PORT=8000" \ -p "${PORT}:3000" \ -p "${BACKEND_PORT}:8000" \ -v "${HOST_DATA_DIR}:/app/backend/data" \ "${IMAGE_NAME}" +echo "Waiting for frontend to be ready..." +for i in 1 2 3 4 5 6 7 8 9 10; do + if curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1:${PORT}/" 2>/dev/null | grep -q 200; then + echo "Frontend ready." + break + fi + if [ "$i" -eq 10 ]; then + echo "WARN: Frontend did not respond with 200 after 10s. Check: docker logs ${CONTAINER_NAME}" + fi + sleep 1 +done + echo "Container started. Data persisted on host: ${HOST_DATA_DIR}" echo "Frontend: http://localhost:${PORT} | Backend API: http://localhost:${BACKEND_PORT} | Health: curl http://localhost:${PORT}/health" diff --git a/src/server.ts b/src/server.ts index 94bfb7e..8c7d99a 100644 --- a/src/server.ts +++ b/src/server.ts @@ -64,8 +64,9 @@ app.get('/health', (_req, res) => { }); const port = process.env.PORT || 3000; +const host = process.env.HOST || '0.0.0.0'; -app.listen(port, () => { +app.listen(Number(port), host, () => { const msg = `Static frontend server listening on port ${port}; access log: ${accessLogPath}`; // eslint-disable-next-line no-console console.log(msg); diff --git a/start.sh b/start.sh index 3c68bcf..a8a501d 100644 --- a/start.sh +++ b/start.sh @@ -1,19 +1,31 @@ #!/usr/bin/env sh -set -e - +# 不 set -e,避免任一进程启动失败时直接退出导致容器无服务 PORT="${PORT:-3000}" BACKEND_PORT="${BACKEND_PORT:-8000}" -echo "Starting FastAPI backend on :${BACKEND_PORT}..." +# 先启前端再启后端,保证至少前端能绑定端口;任一退出不杀另一个 +echo "Starting Node static frontend on 0.0.0.0:${PORT}..." +HOST=0.0.0.0 PORT="${PORT}" BACKEND_PORT="${BACKEND_PORT}" node dist/server.js & +FRONTEND_PID=$! + +echo "Starting FastAPI backend on 0.0.0.0:${BACKEND_PORT}..." uvicorn backend.main:app --host 0.0.0.0 --port "${BACKEND_PORT}" & BACKEND_PID=$! -echo "Starting Node static frontend on :${PORT}..." -PORT="${PORT}" BACKEND_PORT="${BACKEND_PORT}" node dist/server.js & -FRONTEND_PID=$! +sleep 2 +if ! kill -0 "${FRONTEND_PID}" 2>/dev/null; then + echo "WARN: frontend (node) exited, check logs (e.g. node dist/server.js)" +fi +if ! kill -0 "${BACKEND_PID}" 2>/dev/null; then + echo "WARN: backend (uvicorn) exited, check logs" +fi trap 'echo "Stopping services..."; kill ${BACKEND_PID} ${FRONTEND_PID} 2>/dev/null || true' INT TERM -wait -n "${BACKEND_PID}" "${FRONTEND_PID}" +# 两进程都退出才结束,避免一个崩了把另一个也杀掉 +while kill -0 "${FRONTEND_PID}" 2>/dev/null || kill -0 "${BACKEND_PID}" 2>/dev/null; do + wait -n "${FRONTEND_PID}" "${BACKEND_PID}" 2>/dev/null || true + sleep 1 +done