From d00dbbbd03db0344e4e682f359eb8965d02c2bef Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 13:51:43 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E7=94=9F=E4=BA=A7=E6=9E=84=E5=BB=BA=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.properties | 2 +- docker/docker-compose.yaml | 25 +++----- docker/frontend-service-entrypoint.sh | 62 ------------------- docker/frontend-service.Dockerfile | 45 +++++++++++--- 4 files changed, 47 insertions(+), 87 deletions(-) delete mode 100755 docker/frontend-service-entrypoint.sh diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 81032349b..6d7c5bbe5 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -4,7 +4,7 @@ server.port=${SERVER_PORT:8080} # for mysql logging.level.root=${LOG_LEVEL:INFO} logging.level.com.openisle.service.CosImageUploader=DEBUG -spring.datasource.url=jdbc:mysql://${MYSQL_HOST}:3306/${MYSQL_DATABASE} +spring.datasource.url=jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DATABASE} spring.datasource.username=${MYSQL_USER:root} spring.datasource.password=${MYSQL_PASSWORD:password} spring.jpa.hibernate.ddl-auto=update diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 1dfd9b1af..9366e165a 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -212,29 +212,24 @@ services: profiles: - dev - frontend_service: + frontend_service: build: - context: .. - dockerfile: frontend-service.Dockerfile - container_name: openisle-frontend-service - working_dir: /app + context: .. # 仓库根目录(包含 frontend_nuxt/) + dockerfile: docker/frontend-service.Dockerfile + args: + # 由 .env(或 --env-file)提供,默认 staging;正式环境脚本会传 production + NUXT_ENV: ${NUXT_ENV:-staging} + container_name: openisle-frontend env_file: - - ../.env - volumes: - - ../frontend_nuxt:/app - - frontend-service-node-modules:/app/node_modules - - frontend-static:/var/www/openisle + - ../.env # 或者在脚本里指定 .env.staging / .env.production ports: - - "${FRONTEND_SERVICE_PORT:-3001}:3000" + - "${FRONTEND_PORT:-3000}:3000" depends_on: springboot: condition: service_healthy websocket-service: condition: service_healthy - networks: - - openisle-network - profiles: - - service + restart: unless-stopped loopback_8080: image: alpine/socat diff --git a/docker/frontend-service-entrypoint.sh b/docker/frontend-service-entrypoint.sh deleted file mode 100755 index 6e5485647..000000000 --- a/docker/frontend-service-entrypoint.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -cd /app - -echo "👉 Building frontend (Nuxt SSR)..." - -if [ -f .env.production.example ] && [ ! -f .env ]; then - echo "📄 Copying .env.production.example to .env" - cp .env.production.example .env -fi - -npm ci -npm run build - -echo "🧪 Smoke-testing: nuxt generate (artifacts will NOT be used)..." - -SSR_OUTPUT_DIR=".output" -SSR_OUTPUT_BAK=".output-ssr-backup-$$" -GEN_FAIL_MSG="❌ Generate smoke test failed" - -if [ ! -d "${SSR_OUTPUT_DIR}" ]; then - echo "❌ 未发现 ${SSR_OUTPUT_DIR},请先确保 npm run build 成功执行" - exit 1 -fi - -mv "${SSR_OUTPUT_DIR}" "${SSR_OUTPUT_BAK}" - -restore_on_fail() { - if [ -d ".output" ]; then - mv .output ".output-generate-failed-$(date +%s)" || true - fi - mv "${SSR_OUTPUT_BAK}" "${SSR_OUTPUT_DIR}" -} - -trap 'restore_on_fail; echo "${GEN_FAIL_MSG}: unexpected error"; exit 1' ERR - -NUXT_TELEMETRY_DISABLED=1 \ -NITRO_PRERENDER_FAIL_ON_ERROR=1 \ -npx nuxi generate --preset static - -if [ ! -d ".output/public" ]; then - restore_on_fail - echo "${GEN_FAIL_MSG}: .output/public not found" - exit 1 -fi - -rm -rf ".output" -mv "${SSR_OUTPUT_BAK}" "${SSR_OUTPUT_DIR}" -trap - ERR -echo "✅ Generate smoke test passed." - -if [ -d ".output/public" ]; then - mkdir -p /var/www/openisle - rsync -a --delete .output/public/ /var/www/openisle/ -else - echo "❌ 未发现 .output/public;检查 nuxt.config.ts/nitro preset" - exit 1 -fi - -echo "🚀 Starting Nuxt SSR server..." -exec node .output/server/index.mjs diff --git a/docker/frontend-service.Dockerfile b/docker/frontend-service.Dockerfile index f2846e946..132e185e0 100644 --- a/docker/frontend-service.Dockerfile +++ b/docker/frontend-service.Dockerfile @@ -1,12 +1,39 @@ -FROM node:20 - -RUN apt-get update \ - && apt-get install -y --no-install-recommends rsync \ - && rm -rf /var/lib/apt/lists/* - +# ==== builder ==== +FROM node:20-bullseye AS builder WORKDIR /app -COPY docker/frontend-service-entrypoint.sh /usr/local/bin/frontend-service-entrypoint.sh -RUN chmod +x /usr/local/bin/frontend-service-entrypoint.sh +# 通过构建参数选择环境:staging / production(默认 staging) +ARG NUXT_ENV=staging +ENV NODE_ENV=production \ + NUXT_TELEMETRY_DISABLED=1 -CMD ["frontend-service-entrypoint.sh"] +# 复制源代码(假设仓库根目录包含 frontend_nuxt) +# 构建上下文由 docker-compose 指向仓库根目录 +COPY ./frontend_nuxt/package*.json /app/ +RUN npm ci + +# 拷贝剩余代码 +COPY ./frontend_nuxt/ /app/ + +# 若存在环境样例文件,则在构建期复制为 .env(你也可以用 --build-arg 覆盖) +RUN if [ -f ".env.${NUXT_ENV}.example" ]; then cp ".env.${NUXT_ENV}.example" .env; fi + +# 构建 SSR:产物在 .output +RUN npm run build + +# ==== runner ==== +FROM node:20-alpine AS runner +WORKDIR /app +ENV NODE_ENV=production \ + NUXT_TELEMETRY_DISABLED=1 \ + PORT=3000 \ + HOST=0.0.0.0 + +# 复制构建产物 +COPY --from=builder /app/.output /app/.output + +# 健康检查(简洁起见,探测首页) +HEALTHCHECK --interval=10s --timeout=5s --retries=30 CMD wget -qO- http://127.0.0.1:${PORT}/ >/dev/null 2>&1 || exit 1 + +EXPOSE 3000 +CMD ["node", ".output/server/index.mjs"]