From 0d7dc93a67146c90890b1fc98fab268bc93f9656 Mon Sep 17 00:00:00 2001 From: Tim Date: Sun, 28 Sep 2025 21:06:52 +0800 Subject: [PATCH 01/41] =?UTF-8?q?fix:=20=E5=88=9D=E6=AD=A5=E8=BD=AC?= =?UTF-8?q?=E7=A7=BB=E4=B8=BAdocker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 94 ++++++++++++++++++ backend/open-isle.env.example | 3 + .../src/main/resources/application.properties | 20 ++-- docker/.env.example | 20 +--- docker/docker-compose.yaml | 97 +++++++++++++++++-- frontend_nuxt/.env.dev.example | 15 +-- frontend_nuxt/.env.example | 24 +---- frontend_nuxt/.env.production.example | 16 +-- frontend_nuxt/.env.staging.example | 20 +--- .../websocket_service.env.example | 2 + 10 files changed, 215 insertions(+), 96 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..00624c513 --- /dev/null +++ b/.env.example @@ -0,0 +1,94 @@ +# === Core Service Ports === +SERVER_PORT=8080 +FRONTEND_PORT=3000 +WEBSOCKET_PORT=8082 +MYSQL_PORT=3306 +REDIS_PORT=6379 +RABBITMQ_PORT=5672 +RABBITMQ_MANAGEMENT_PORT=15672 + +# === OpenSearch Configuration === +OPENSEARCH_PORT=9200 +OPENSEARCH_METRICS_PORT=9600 +OPENSEARCH_DASHBOARDS_PORT=5601 +OPENSEARCH_ENABLED=true +OPENSEARCH_SCHEME=http +OPENSEARCH_USERNAME= +OPENSEARCH_PASSWORD= + +# === Database Configuration === +MYSQL_DATABASE=openisle +MYSQL_ROOT_PASSWORD= +MYSQL_USER= +MYSQL_PASSWORD= +MYSQL_HOST= + +# === Redis Configuration === +REDIS_HOST=redis +REDIS_DATABASE=0 + +# === RabbitMQ Configuration === +RABBITMQ_HOST=rabbitmq +RABBITMQ_USERNAME=openisle +RABBITMQ_PASSWORD=openisle_password + +# === Backend Application Secrets === +JWT_SECRET=change-me-jwt-secret +JWT_REASON_SECRET=change-me-jwt-reason-secret +JWT_RESET_SECRET=change-me-jwt-reset-secret +JWT_INVITE_SECRET=change-me-jwt-invite-secret +JWT_EXPIRATION=2592000000 +PASSWORD_STRENGTH=LOW +POST_PUBLISH_MODE=DIRECT +REGISTER_MODE=WHITELIST +UPLOAD_CHECK_TYPE=true +UPLOAD_MAX_SIZE=5242880 +AVATAR_STYLE=pixel-art-neutral +AVATAR_SIZE=128 +AVATAR_BASE_URL=https://api.dicebear.com/6.x +USER_POSTS_LIMIT=10 +USER_REPLIES_LIMIT=50 +SNIPPET_LENGTH=200 +SEARCH_INDEX_PREFIX=openisle +SEARCH_HIGHLIGHT_FRAGMENT_SIZE=200 +SEARCH_REINDEX_ON_STARTUP=true +SEARCH_REINDEX_BATCH_SIZE=500 +CAPTCHA_ENABLED=false +RECAPTCHA_SECRET_KEY= +CAPTCHA_REGISTER_ENABLED=false +CAPTCHA_LOGIN_ENABLED=false +CAPTCHA_POST_ENABLED=false +CAPTCHA_COMMENT_ENABLED=false +RESEND_API_KEY= +RESEND_FROM_EMAIL= +COS_BASE_URL=https://<你的cos>.cos.accelerate.myqcloud.com +COS_SECRET_ID= +COS_SECRET_KEY= +COS_REGION=ap-guangzhou +COS_BUCKET_NAME= +GOOGLE_CLIENT_ID= +GITHUB_CLIENT_ID= +GITHUB_CLIENT_SECRET= +DISCORD_CLIENT_ID= +DISCORD_CLIENT_SECRET= +TWITTER_CLIENT_ID= +TWITTER_CLIENT_SECRET= +TELEGRAM_BOT_TOKEN= +OPENAI_API_KEY= +OPENAI_MODEL=gpt-4o +AI_FORMAT_LIMIT=3 +WEBSITE_URL=http://localhost:3000 +WEBPUSH_PUBLIC_KEY= +WEBPUSH_PRIVATE_KEY= +LOG_LEVEL=INFO + +# === Frontend (Nuxt) === +NUXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8080 +NUXT_PUBLIC_WEBSOCKET_URL=https://127.0.0.1:8082 +NUXT_PUBLIC_WEBSITE_BASE_URL=http://localhost:3000 +NUXT_PUBLIC_GOOGLE_CLIENT_ID=777830451304-nt8afkkap18gui4f9entcha99unal744.apps.googleusercontent.com +NUXT_PUBLIC_GITHUB_CLIENT_ID=Ov23liOlrZnPKRF7s7NN +NUXT_PUBLIC_DISCORD_CLIENT_ID=1394985417044000779 +NUXT_PUBLIC_TWITTER_CLIENT_ID=ZTRTU05KSk9KTTJrTTdrVC1tc1E6MTpjaQ +NUXT_PUBLIC_TELEGRAM_BOT_ID=8450237135 + diff --git a/backend/open-isle.env.example b/backend/open-isle.env.example index a62ac877f..261c45b17 100644 --- a/backend/open-isle.env.example +++ b/backend/open-isle.env.example @@ -1,3 +1,6 @@ +# 所有环境变量已集中在仓库根目录的 .env.*.example 文件。 +# 此文件保留作参考用途,如需在 Docker 之外手动配置,可按需复制。 + # === Spring Boot === SERVER_PORT=8080 diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 479fc683c..b59065e3f 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=${MYSQL_URL:jdbc:mysql://localhost:3306/openisle} +spring.datasource.url=jdbc:mysql://${MYSQL_HOST}:3306/${MYSQL_DATABASE} spring.datasource.username=${MYSQL_USER:root} spring.datasource.password=${MYSQL_PASSWORD:password} spring.jpa.hibernate.ddl-auto=update @@ -47,11 +47,11 @@ app.snippet-length=${SNIPPET_LENGTH:200} # OpenSearch integration app.search.enabled=${SEARCH_ENABLED:true} -app.search.host=${SEARCH_HOST:localhost} -app.search.port=${SEARCH_PORT:9200} -app.search.scheme=${SEARCH_SCHEME:http} -app.search.username=${SEARCH_USERNAME:} -app.search.password=${SEARCH_PASSWORD:} +app.search.host=${OPENSEARCH_HOST:localhost} +app.search.port=${OPENSEARCH_PORT:9200} +app.search.scheme=${OPENSEARCH_SCHEME:http} +app.search.username=${OPENSEARCH_USERNAME:} +app.search.password=${OPENSEARCH_PASSWORD:} app.search.index-prefix=${SEARCH_INDEX_PREFIX:openisle} app.search.highlight-fragment-size=${SEARCH_HIGHLIGHT_FRAGMENT_SIZE:${SNIPPET_LENGTH:200}} app.search.reindex-on-startup=${SEARCH_REINDEX_ON_STARTUP:true} @@ -81,15 +81,15 @@ cos.bucket-name=${COS_BUCKET_NAME:} # your image upload services: ... # Google OAuth configuration -google.client-id=${GOOGLE_CLIENT_ID:} +google.client-id=${NUXT_PUBLIC_GOOGLE_CLIENT_ID:} # GitHub OAuth configuration -github.client-id=${GITHUB_CLIENT_ID:} +github.client-id=${NUXT_PUBLIC_GITHUB_CLIENT_ID:} github.client-secret=${GITHUB_CLIENT_SECRET:} # Discord OAuth configuration -discord.client-id=${DISCORD_CLIENT_ID:} +discord.client-id=${NUXT_PUBLIC_DISCORD_CLIENT_ID:} discord.client-secret=${DISCORD_CLIENT_SECRET:} # Twitter OAuth configuration -twitter.client-id=${TWITTER_CLIENT_ID:} +twitter.client-id=${NUXT_PUBLIC_TWITTER_CLIENT_ID:} twitter.client-secret=${TWITTER_CLIENT_SECRET:} # Telegram login configuration telegram.bot-token=${TELEGRAM_BOT_TOKEN:} diff --git a/docker/.env.example b/docker/.env.example index 0ad80a93c..a798793ea 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -1,16 +1,4 @@ -# 前端访问端口 -SERVER_PORT=8080 - -# OpenSearch 配置 -OPENSEARCH_PORT=9200 -OPENSEARCH_METRICS_PORT=9600 -OPENSEARCH_DASHBOARDS_PORT=5601 - -# MySQL 配置 -MYSQL_ROOT_PASSWORD=toor - -# 会覆盖 `open-isle.env` -MYSQL_PORT=3306 -MYSQL_DATABASE=openisle -MYSQL_USER=<数据库用户名> -MYSQL_PASSWORD=<数据库密码> +# 已迁移到仓库根目录的 .env.*.example 文件。 +# 请复制对应环境的示例文件到项目根目录,例如: +# cp ../.env.dev.example ../.env +# docker-compose 将自动读取 ../.env。 diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 50a60557d..58c0e1150 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -5,16 +5,20 @@ services: container_name: openisle-mysql restart: always env_file: - - ../backend/open-isle.env - - ./.env + - ../.env + environment: + MYSQL_DATABASE: ${MYSQL_DATABASE} + MYSQL_USER: ${MYSQL_USER} + MYSQL_PASSWORD: ${MYSQL_PASSWORD} + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} ports: - - "${MYSQL_PORT}:3306" + - "${MYSQL_PORT:-3306}:3306" volumes: - mysql-data:/var/lib/mysql - ../backend/src/main/resources/db/init:/docker-entrypoint-initdb.d networks: - openisle-network - + # OpenSearch Service opensearch: build: @@ -52,6 +56,35 @@ services: - opensearch restart: unless-stopped + rabbitmq: + image: rabbitmq:3.13-management + container_name: openisle-rabbitmq + restart: unless-stopped + env_file: + - ../.env + environment: + RABBITMQ_DEFAULT_USER: ${RABBITMQ_USERNAME} + RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD} + ports: + - "${RABBITMQ_PORT:-5672}:5672" + - "${RABBITMQ_MANAGEMENT_PORT:-15672}:15672" + volumes: + - rabbitmq-data:/var/lib/rabbitmq + networks: + - openisle-network + + redis: + image: redis:7 + container_name: openisle-redis + restart: unless-stopped + env_file: + - ../.env + ports: + - "${REDIS_PORT:-6379}:6379" + volumes: + - redis-data:/data + networks: + - openisle-network # Java spring boot service springboot: @@ -59,21 +92,63 @@ services: container_name: openisle-springboot working_dir: /app env_file: - - ../backend/open-isle.env - - ./.env - environment: - - MYSQL_URL=jdbc:mysql://mysql:${MYSQL_PORT}/${MYSQL_DATABASE}?useUnicode=yes&characterEncoding=UTF-8&useInformationSchema=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true + - ../.env ports: - - "${SERVER_PORT}:8080" + - "${SERVER_PORT:-8080}:${SERVER_PORT:-8080}" volumes: - ../backend:/app - maven-repo:/root/.m2 depends_on: - mysql + - redis + - rabbitmq command: mvn clean spring-boot:run -Dmaven.test.skip=true networks: - openisle-network + websocket-service: + image: maven:3.9-eclipse-temurin-17 + container_name: openisle-websocket + working_dir: /app + env_file: + - ../.env + environment: + SERVER_PORT: ${WEBSOCKET_PORT} + RABBITMQ_HOST: ${RABBITMQ_HOST} + RABBITMQ_PORT: ${RABBITMQ_PORT} + RABBITMQ_USERNAME: ${RABBITMQ_USERNAME} + RABBITMQ_PASSWORD: ${RABBITMQ_PASSWORD} + JWT_SECRET: ${JWT_SECRET} + WEBSITE_URL: ${WEBSITE_URL} + ports: + - "${WEBSOCKET_PORT:-8082}:${WEBSOCKET_PORT:-8082}" + volumes: + - ../websocket_service:/app + - websocket-maven-repo:/root/.m2 + depends_on: + - rabbitmq + command: mvn clean spring-boot:run -Dmaven.test.skip=true + networks: + - openisle-network + + frontend: + image: node:20 + container_name: openisle-frontend + working_dir: /app + env_file: + - ../.env + command: sh -c "npm install && npm run dev" + volumes: + - ../frontend_nuxt:/app + - frontend-node-modules:/app/node_modules + ports: + - "${FRONTEND_PORT:-3000}:3000" + depends_on: + - springboot + - websocket-service + networks: + - openisle-network + networks: openisle-network: driver: bridge @@ -81,3 +156,7 @@ networks: volumes: mysql-data: maven-repo: + redis-data: + rabbitmq-data: + websocket-maven-repo: + frontend-node-modules: diff --git a/frontend_nuxt/.env.dev.example b/frontend_nuxt/.env.dev.example index bb0ee2635..9a41ba7af 100644 --- a/frontend_nuxt/.env.dev.example +++ b/frontend_nuxt/.env.dev.example @@ -1,12 +1,3 @@ -; 本地部署后端 -NUXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8080 -NUXT_PUBLIC_WEBSOCKET_URL=https://127.0.0.1:8082 -NUXT_PUBLIC_WEBSITE_BASE_URL=http://localhost:3000 - -NUXT_PUBLIC_GOOGLE_CLIENT_ID=777830451304-nt8afkkap18gui4f9entcha99unal744.apps.googleusercontent.com -# NUXT_PUBLIC_GITHUB_CLIENT_ID=Ov23liVkO1NPAX5JyWxJ -; 本地 -NUXT_PUBLIC_GITHUB_CLIENT_ID=Ov23liOlrZnPKRF7s7NN -NUXT_PUBLIC_DISCORD_CLIENT_ID=1394985417044000779 -NUXT_PUBLIC_TWITTER_CLIENT_ID=ZTRTU05KSk9KTTJrTTdrVC1tc1E6MTpjaQ -NUXT_PUBLIC_TELEGRAM_BOT_ID=8450237135 +# 环境变量已统一迁移至仓库根目录的 .env.*.example 文件。 +# 如需在本地运行 Nuxt,请复制对应的示例文件到项目根目录: +# cp ../.env.dev.example ../.env diff --git a/frontend_nuxt/.env.example b/frontend_nuxt/.env.example index dadb36387..bcbdb7bf6 100644 --- a/frontend_nuxt/.env.example +++ b/frontend_nuxt/.env.example @@ -1,19 +1,5 @@ -; 本地部署后端 -; NUXT_PUBLIC_API_BASE_URL=https://127.0.0.1:8081 -; 预发环境后端 -; NUXT_PUBLIC_API_BASE_URL=https://staging.open-isle.com -; 生产环境后端 -NUXT_PUBLIC_API_BASE_URL=https://open-isle.com - -; 生产环境ws后端 -NUXT_PUBLIC_WEBSOCKET_URL=https://open-isle.com/websocket - -; 预发环境 -; NUXT_PUBLIC_WEBSITE_BASE_URL=https://staging.open-isle.com -; 正式环境/生产环境 -NUXT_PUBLIC_WEBSITE_BASE_URL=https://open-isle.com -NUXT_PUBLIC_GOOGLE_CLIENT_ID=777830451304-nt8afkkap18gui4f9entcha99unal744.apps.googleusercontent.com -NUXT_PUBLIC_GITHUB_CLIENT_ID=Ov23liVkO1NPAX5JyWxJ -NUXT_PUBLIC_DISCORD_CLIENT_ID=1394985417044000779 -NUXT_PUBLIC_TWITTER_CLIENT_ID=ZTRTU05KSk9KTTJrTTdrVC1tc1E6MTpjaQ -NUXT_PUBLIC_TELEGRAM_BOT_ID=8450237135 +# 环境变量已统一迁移至仓库根目录的 .env.*.example 文件。 +# 根据环境选择对应文件复制至项目根目录: +# cp ../.env.dev.example ../.env +# cp ../.env.staging.example ../.env +# cp ../.env.production.example ../.env diff --git a/frontend_nuxt/.env.production.example b/frontend_nuxt/.env.production.example index a1bff6842..ee3573dd6 100644 --- a/frontend_nuxt/.env.production.example +++ b/frontend_nuxt/.env.production.example @@ -1,13 +1,3 @@ - -; 生产环境后端 -NUXT_PUBLIC_API_BASE_URL=https://www.open-isle.com -; 正式环境/生产环境 -NUXT_PUBLIC_WEBSITE_BASE_URL=https://www.open-isle.com -; 生产环境ws后端 -NUXT_PUBLIC_WEBSOCKET_URL=https://www.open-isle.com/websocket - -NUXT_PUBLIC_GOOGLE_CLIENT_ID=777830451304-nt8afkkap18gui4f9entcha99unal744.apps.googleusercontent.com -NUXT_PUBLIC_GITHUB_CLIENT_ID=Ov23liVkO1NPAX5JyWxJ -NUXT_PUBLIC_DISCORD_CLIENT_ID=1394985417044000779 -NUXT_PUBLIC_TWITTER_CLIENT_ID=ZTRTU05KSk9KTTJrTTdrVC1tc1E6MTpjaQ -NUXT_PUBLIC_TELEGRAM_BOT_ID=8450237135 +# 环境变量已统一迁移至仓库根目录的 .env.*.example 文件。 +# 如需配置生产环境,请复制并修改对应示例文件: +# cp ../.env.production.example ../.env diff --git a/frontend_nuxt/.env.staging.example b/frontend_nuxt/.env.staging.example index 0cc8ef140..dde477e44 100644 --- a/frontend_nuxt/.env.staging.example +++ b/frontend_nuxt/.env.staging.example @@ -1,17 +1,3 @@ -; 本地部署后端 -; NUXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8080 - -; 预发环境后端 -NUXT_PUBLIC_API_BASE_URL=https://staging.open-isle.com - -; 预发环境ws后端 -NUXT_PUBLIC_WEBSOCKET_URL=https://staging.open-isle.com/websocket - -; 预发环境 -NUXT_PUBLIC_WEBSITE_BASE_URL=https://staging.open-isle.com - -NUXT_PUBLIC_GOOGLE_CLIENT_ID=777830451304-nt8afkkap18gui4f9entcha99unal744.apps.googleusercontent.com -NUXT_PUBLIC_GITHUB_CLIENT_ID=Ov23liVkO1NPAX5JyWxJ -NUXT_PUBLIC_DISCORD_CLIENT_ID=1394985417044000779 -NUXT_PUBLIC_TWITTER_CLIENT_ID=ZTRTU05KSk9KTTJrTTdrVC1tc1E6MTpjaQ -NUXT_PUBLIC_TELEGRAM_BOT_ID=8450237135 +# 环境变量已统一迁移至仓库根目录的 .env.*.example 文件。 +# 如需配置预发环境,请复制并修改对应示例文件: +# cp ../.env.staging.example ../.env diff --git a/websocket_service/websocket_service.env.example b/websocket_service/websocket_service.env.example index 9f6304269..79e51ccdf 100644 --- a/websocket_service/websocket_service.env.example +++ b/websocket_service/websocket_service.env.example @@ -1,3 +1,5 @@ +# 所有环境变量已集中在仓库根目录的 .env.*.example 文件。 +# 如需在独立环境中运行,可参考以下字段: SERVER_PORT= # RabbitMQ 配置 From 39ae8c02cbf4bbcb70f437e52d30c29a4936334a Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 10:29:37 +0800 Subject: [PATCH 02/41] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9.env.example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index 00624c513..197b29a0e 100644 --- a/.env.example +++ b/.env.example @@ -21,7 +21,7 @@ MYSQL_DATABASE=openisle MYSQL_ROOT_PASSWORD= MYSQL_USER= MYSQL_PASSWORD= -MYSQL_HOST= +MYSQL_HOST=localhost # === Redis Configuration === REDIS_HOST=redis @@ -66,12 +66,8 @@ COS_SECRET_ID= COS_SECRET_KEY= COS_REGION=ap-guangzhou COS_BUCKET_NAME= -GOOGLE_CLIENT_ID= -GITHUB_CLIENT_ID= GITHUB_CLIENT_SECRET= -DISCORD_CLIENT_ID= DISCORD_CLIENT_SECRET= -TWITTER_CLIENT_ID= TWITTER_CLIENT_SECRET= TELEGRAM_BOT_TOKEN= OPENAI_API_KEY= @@ -86,9 +82,16 @@ LOG_LEVEL=INFO NUXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8080 NUXT_PUBLIC_WEBSOCKET_URL=https://127.0.0.1:8082 NUXT_PUBLIC_WEBSITE_BASE_URL=http://localhost:3000 +# 线上 & 本地均可使用 NUXT_PUBLIC_GOOGLE_CLIENT_ID=777830451304-nt8afkkap18gui4f9entcha99unal744.apps.googleusercontent.com +# 线上 NUXT_PUBLIC_GITHUB_CLIENT_ID=Ov23liOlrZnPKRF7s7NN +# 本地 +# NUXT_PUBLIC_GITHUB_CLIENT_ID=Ov23liOlrZnPKRF7s7NN +# 线上 & 本地均可使用 NUXT_PUBLIC_DISCORD_CLIENT_ID=1394985417044000779 +# 线上 & 本地均可使用 NUXT_PUBLIC_TWITTER_CLIENT_ID=ZTRTU05KSk9KTTJrTTdrVC1tc1E6MTpjaQ +# 线上 NUXT_PUBLIC_TELEGRAM_BOT_ID=8450237135 From 208c8758682955a86419555b2eb020af1a77cccf Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 10:42:17 +0800 Subject: [PATCH 03/41] =?UTF-8?q?fix:=20=E5=8E=BB=E9=99=A4compose=E4=B8=AD?= =?UTF-8?q?=E9=87=8D=E5=A4=8D=E5=A3=B0=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 6 +++--- docker/docker-compose.yaml | 17 +---------------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/.env.example b/.env.example index 197b29a0e..038182d43 100644 --- a/.env.example +++ b/.env.example @@ -28,9 +28,9 @@ REDIS_HOST=redis REDIS_DATABASE=0 # === RabbitMQ Configuration === -RABBITMQ_HOST=rabbitmq -RABBITMQ_USERNAME=openisle -RABBITMQ_PASSWORD=openisle_password +RABBITMQ_HOST=localhost +RABBITMQ_USERNAME=guest +RABBITMQ_PASSWORD=guest # === Backend Application Secrets === JWT_SECRET=change-me-jwt-secret diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 58c0e1150..29c8b432a 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -6,11 +6,6 @@ services: restart: always env_file: - ../.env - environment: - MYSQL_DATABASE: ${MYSQL_DATABASE} - MYSQL_USER: ${MYSQL_USER} - MYSQL_PASSWORD: ${MYSQL_PASSWORD} - MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} ports: - "${MYSQL_PORT:-3306}:3306" volumes: @@ -62,9 +57,6 @@ services: restart: unless-stopped env_file: - ../.env - environment: - RABBITMQ_DEFAULT_USER: ${RABBITMQ_USERNAME} - RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD} ports: - "${RABBITMQ_PORT:-5672}:5672" - "${RABBITMQ_MANAGEMENT_PORT:-15672}:15672" @@ -102,6 +94,7 @@ services: - mysql - redis - rabbitmq + - websocket-service command: mvn clean spring-boot:run -Dmaven.test.skip=true networks: - openisle-network @@ -112,14 +105,6 @@ services: working_dir: /app env_file: - ../.env - environment: - SERVER_PORT: ${WEBSOCKET_PORT} - RABBITMQ_HOST: ${RABBITMQ_HOST} - RABBITMQ_PORT: ${RABBITMQ_PORT} - RABBITMQ_USERNAME: ${RABBITMQ_USERNAME} - RABBITMQ_PASSWORD: ${RABBITMQ_PASSWORD} - JWT_SECRET: ${JWT_SECRET} - WEBSITE_URL: ${WEBSITE_URL} ports: - "${WEBSOCKET_PORT:-8082}:${WEBSOCKET_PORT:-8082}" volumes: From a12368602d7a7902af21a6dba2a724953a5f0536 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 10:52:59 +0800 Subject: [PATCH 04/41] =?UTF-8?q?fix:=20=E5=B0=9D=E8=AF=95docker=E9=83=A8?= =?UTF-8?q?=E7=BD=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 docker/.gitignore diff --git a/docker/.gitignore b/docker/.gitignore new file mode 100644 index 000000000..6320cd248 --- /dev/null +++ b/docker/.gitignore @@ -0,0 +1 @@ +data \ No newline at end of file From bb955c98bae229f3313fe002a7f07b0110a9f296 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 15:16:32 +0800 Subject: [PATCH 05/41] =?UTF-8?q?fix:=20=E5=90=8E=E5=8F=B0=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E9=93=BE=E6=8E=A5=E5=90=84=E4=B8=AA=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 2 +- .../src/main/resources/application.properties | 2 +- docker/docker-compose.yaml | 66 +++++++++++++++++-- docker/frontend-service-entrypoint.sh | 62 +++++++++++++++++ docker/frontend-service.Dockerfile | 12 ++++ docker/{DockerFile => opensearch.Dockerfile} | 0 6 files changed, 135 insertions(+), 9 deletions(-) create mode 100755 docker/frontend-service-entrypoint.sh create mode 100644 docker/frontend-service.Dockerfile rename docker/{DockerFile => opensearch.Dockerfile} (100%) diff --git a/.env.example b/.env.example index 038182d43..5a2bbdcb6 100644 --- a/.env.example +++ b/.env.example @@ -28,7 +28,7 @@ REDIS_HOST=redis REDIS_DATABASE=0 # === RabbitMQ Configuration === -RABBITMQ_HOST=localhost +RABBITMQ_HOST=local RABBITMQ_USERNAME=guest RABBITMQ_PASSWORD=guest diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index b59065e3f..4362668b3 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -47,7 +47,7 @@ app.snippet-length=${SNIPPET_LENGTH:200} # OpenSearch integration app.search.enabled=${SEARCH_ENABLED:true} -app.search.host=${OPENSEARCH_HOST:localhost} +app.search.host=${OPENSEARCH_HOST:opensearch} app.search.port=${OPENSEARCH_PORT:9200} app.search.scheme=${OPENSEARCH_SCHEME:http} app.search.username=${OPENSEARCH_USERNAME:} diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 29c8b432a..178a74536 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -13,12 +13,18 @@ services: - ../backend/src/main/resources/db/init:/docker-entrypoint-initdb.d networks: - openisle-network + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-u", "root", "-p$MYSQL_ROOT_PASSWORD"] + interval: 5s + timeout: 3s + retries: 30 + start_period: 20s # OpenSearch Service opensearch: build: context: . - dockerfile: Dockerfile + dockerfile: opensearch.Dockerfile container_name: opensearch environment: - cluster.name=os-single @@ -38,6 +44,14 @@ services: - "${OPENSEARCH_PORT:-9200}:9200" - "${OPENSEARCH_METRICS_PORT:-9600}:9600" restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:9200/_cluster/health >/dev/null"] + interval: 10s + timeout: 5s + retries: 30 + start_period: 60s + networks: + - openisle-network dashboards: image: opensearchproject/opensearch-dashboards:3.0.0 @@ -50,6 +64,8 @@ services: depends_on: - opensearch restart: unless-stopped + networks: + - openisle-network rabbitmq: image: rabbitmq:3.13-management @@ -85,16 +101,26 @@ services: working_dir: /app env_file: - ../.env + environment: + - MYSQL_HOST=mysql + - OPENSEARCH_HOST=opensearch + - RABBITMQ_HOST=rabbitmq ports: - "${SERVER_PORT:-8080}:${SERVER_PORT:-8080}" volumes: - ../backend:/app - maven-repo:/root/.m2 depends_on: - - mysql - - redis - - rabbitmq - - websocket-service + mysql: + condition: service_healthy + redis: + condition: service_started + rabbitmq: + condition: service_started + websocket-service: + condition: service_started + opensearch: + condition: service_healthy command: mvn clean spring-boot:run -Dmaven.test.skip=true networks: - openisle-network @@ -116,9 +142,9 @@ services: networks: - openisle-network - frontend: + frontend_dev: image: node:20 - container_name: openisle-frontend + container_name: openisle-frontend-dev working_dir: /app env_file: - ../.env @@ -133,6 +159,30 @@ services: - websocket-service networks: - openisle-network + profiles: + - dev + + frontend_service: + build: + context: .. + dockerfile: frontend-service.Dockerfile + container_name: openisle-frontend-service + working_dir: /app + env_file: + - ../.env + volumes: + - ../frontend_nuxt:/app + - frontend-service-node-modules:/app/node_modules + - frontend-static:/var/www/openisle + ports: + - "${FRONTEND_SERVICE_PORT:-3001}:3000" + depends_on: + - springboot + - websocket-service + networks: + - openisle-network + profiles: + - service networks: openisle-network: @@ -145,3 +195,5 @@ volumes: rabbitmq-data: websocket-maven-repo: frontend-node-modules: + frontend-service-node-modules: + frontend-static: diff --git a/docker/frontend-service-entrypoint.sh b/docker/frontend-service-entrypoint.sh new file mode 100755 index 000000000..6e5485647 --- /dev/null +++ b/docker/frontend-service-entrypoint.sh @@ -0,0 +1,62 @@ +#!/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 new file mode 100644 index 000000000..f2846e946 --- /dev/null +++ b/docker/frontend-service.Dockerfile @@ -0,0 +1,12 @@ +FROM node:20 + +RUN apt-get update \ + && apt-get install -y --no-install-recommends rsync \ + && rm -rf /var/lib/apt/lists/* + +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 + +CMD ["frontend-service-entrypoint.sh"] diff --git a/docker/DockerFile b/docker/opensearch.Dockerfile similarity index 100% rename from docker/DockerFile rename to docker/opensearch.Dockerfile From 06d76438e8a4eb2e9d88fac179c2a33cf110aa28 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 16:04:14 +0800 Subject: [PATCH 06/41] =?UTF-8?q?fix:=20=E5=89=8D=E7=AB=AF=E5=88=9D?= =?UTF-8?q?=E6=AD=A5=E8=B0=83=E9=80=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 10 ++++++---- .../main/java/com/openisle/config/SecurityConfig.java | 2 ++ docker/docker-compose.yaml | 4 ---- frontend_nuxt/nuxt.config.ts | 4 +++- .../openisle/websocket/security/SecurityConfig.java | 2 ++ 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index 5a2bbdcb6..887a948b2 100644 --- a/.env.example +++ b/.env.example @@ -15,20 +15,21 @@ OPENSEARCH_ENABLED=true OPENSEARCH_SCHEME=http OPENSEARCH_USERNAME= OPENSEARCH_PASSWORD= +OPENSEARCH_HOST=opensearch # === Database Configuration === MYSQL_DATABASE=openisle MYSQL_ROOT_PASSWORD= MYSQL_USER= MYSQL_PASSWORD= -MYSQL_HOST=localhost +MYSQL_HOST=mysql # === Redis Configuration === REDIS_HOST=redis REDIS_DATABASE=0 # === RabbitMQ Configuration === -RABBITMQ_HOST=local +RABBITMQ_HOST=rabbitmq RABBITMQ_USERNAME=guest RABBITMQ_PASSWORD=guest @@ -79,8 +80,9 @@ WEBPUSH_PRIVATE_KEY= LOG_LEVEL=INFO # === Frontend (Nuxt) === -NUXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8080 -NUXT_PUBLIC_WEBSOCKET_URL=https://127.0.0.1:8082 +NUXT_PUBLIC_API_BASE_URL=http://springboot:8080 +NUXT_PUBLIC_API_BASE_URL_SSR=http://localhost:8080 +NUXT_PUBLIC_WEBSOCKET_URL=http://websocket_service:8082 NUXT_PUBLIC_WEBSITE_BASE_URL=http://localhost:3000 # 线上 & 本地均可使用 NUXT_PUBLIC_GOOGLE_CLIENT_ID=777830451304-nt8afkkap18gui4f9entcha99unal744.apps.googleusercontent.com diff --git a/backend/src/main/java/com/openisle/config/SecurityConfig.java b/backend/src/main/java/com/openisle/config/SecurityConfig.java index 4bd8e735f..b2d0da85e 100644 --- a/backend/src/main/java/com/openisle/config/SecurityConfig.java +++ b/backend/src/main/java/com/openisle/config/SecurityConfig.java @@ -97,6 +97,8 @@ public class SecurityConfig { "http://localhost:8081", "http://localhost:8082", "http://localhost:3000", + "http://frontend_dev:3000", + "http://frontend_service:3000", "http://localhost:3001", "http://localhost", "http://30.211.97.238:3000", diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 178a74536..2f82594ee 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -101,10 +101,6 @@ services: working_dir: /app env_file: - ../.env - environment: - - MYSQL_HOST=mysql - - OPENSEARCH_HOST=opensearch - - RABBITMQ_HOST=rabbitmq ports: - "${SERVER_PORT:-8080}:${SERVER_PORT:-8080}" volumes: diff --git a/frontend_nuxt/nuxt.config.ts b/frontend_nuxt/nuxt.config.ts index 0c5bea8ac..b2c7784b7 100644 --- a/frontend_nuxt/nuxt.config.ts +++ b/frontend_nuxt/nuxt.config.ts @@ -9,7 +9,9 @@ export default defineNuxtConfig({ modules: ['@nuxt/image'], runtimeConfig: { public: { - apiBaseUrl: process.env.NUXT_PUBLIC_API_BASE_URL || '', + apiBaseUrl: process.server + ? process.env.NUXT_PUBLIC_API_BASE_URL_SSR + : process.env.NUXT_PUBLIC_API_BASE_URL, websocketUrl: process.env.NUXT_PUBLIC_WEBSOCKET_URL || '', websiteBaseUrl: process.env.NUXT_PUBLIC_WEBSITE_BASE_URL || '', googleClientId: process.env.NUXT_PUBLIC_GOOGLE_CLIENT_ID || '', diff --git a/websocket_service/src/main/java/com/openisle/websocket/security/SecurityConfig.java b/websocket_service/src/main/java/com/openisle/websocket/security/SecurityConfig.java index 06b924bd8..6d6da7faa 100644 --- a/websocket_service/src/main/java/com/openisle/websocket/security/SecurityConfig.java +++ b/websocket_service/src/main/java/com/openisle/websocket/security/SecurityConfig.java @@ -37,6 +37,8 @@ public class SecurityConfig { "http://localhost:8081", "http://localhost:8082", "http://localhost:3000", + "http://frontend_dev:3000", + "http://frontend_service:3000", "http://localhost:3001", "http://localhost", "http://30.211.97.238:3000", From 4080f60f60d412a36289b906d4d13ffb59dcee7e Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 16:46:25 +0800 Subject: [PATCH 07/41] =?UTF-8?q?fix:=20rabbitmq=20=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 4 +- docker/docker-compose.yaml | 57 +++++++++++++++++++++++----- docker/rabbitmq/conf/enabled_plugins | 1 + docker/rabbitmq/conf/rabbitmq.conf | 6 +++ docker/rabbitmq/definitions.json | 31 +++++++++++++++ 5 files changed, 88 insertions(+), 11 deletions(-) create mode 100644 docker/rabbitmq/conf/enabled_plugins create mode 100644 docker/rabbitmq/conf/rabbitmq.conf create mode 100644 docker/rabbitmq/definitions.json diff --git a/.env.example b/.env.example index 887a948b2..b89b03aff 100644 --- a/.env.example +++ b/.env.example @@ -30,8 +30,8 @@ REDIS_DATABASE=0 # === RabbitMQ Configuration === RABBITMQ_HOST=rabbitmq -RABBITMQ_USERNAME=guest -RABBITMQ_PASSWORD=guest +RABBITMQ_USERNAME=nagisa +RABBITMQ_PASSWORD=nagisa # === Backend Application Secrets === JWT_SECRET=change-me-jwt-secret diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 2f82594ee..029c654e4 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -71,16 +71,26 @@ services: image: rabbitmq:3.13-management container_name: openisle-rabbitmq restart: unless-stopped - env_file: - - ../.env + environment: + RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_VHOST:-/} ports: - "${RABBITMQ_PORT:-5672}:5672" - "${RABBITMQ_MANAGEMENT_PORT:-15672}:15672" volumes: - rabbitmq-data:/var/lib/rabbitmq + - ./rabbitmq/conf/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf:ro + - ./rabbitmq/conf/enabled_plugins:/etc/rabbitmq/enabled_plugins:ro + - ./rabbitmq/definitions.json:/etc/rabbitmq/definitions.json:ro + healthcheck: + test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"] + interval: 10s + timeout: 5s + retries: 30 + start_period: 30s networks: - openisle-network + redis: image: redis:7 container_name: openisle-redis @@ -101,6 +111,9 @@ services: working_dir: /app env_file: - ../.env + environment: + SPRING_HEALTH_PATH: ${SPRING_HEALTH_PATH:-/actuator/health} + SERVER_PORT: ${SERVER_PORT:-8080} ports: - "${SERVER_PORT:-8080}:${SERVER_PORT:-8080}" volumes: @@ -117,7 +130,16 @@ services: condition: service_started opensearch: condition: service_healthy - command: mvn clean spring-boot:run -Dmaven.test.skip=true + command: > + sh -c "apt-get update && apt-get install -y --no-install-recommends curl && + mvn clean spring-boot:run -Dmaven.test.skip=true" + # healthcheck: + # test: ["CMD-SHELL", + # "curl -fsS http://127.0.0.1:${SERVER_PORT:-8080}${SPRING_HEALTH_PATH:-/actuator/health} | grep -q '\"status\"\\s*:\\s*\"UP\"'"] + # interval: 10s + # timeout: 5s + # retries: 30 + # start_period: 90s networks: - openisle-network @@ -127,14 +149,27 @@ services: working_dir: /app env_file: - ../.env + environment: + WS_HEALTH_PATH: ${WS_HEALTH_PATH:-/actuator/health} + WEBSOCKET_PORT: ${WEBSOCKET_PORT:-8082} ports: - "${WEBSOCKET_PORT:-8082}:${WEBSOCKET_PORT:-8082}" volumes: - ../websocket_service:/app - websocket-maven-repo:/root/.m2 depends_on: - - rabbitmq - command: mvn clean spring-boot:run -Dmaven.test.skip=true + rabbitmq: + condition: service_healthy + command: > + sh -c "apt-get update && apt-get install -y --no-install-recommends curl && + mvn clean spring-boot:run -Dmaven.test.skip=true" + # healthcheck: + # test: ["CMD-SHELL", + # "curl -fsS http://127.0.0.1:${WEBSOCKET_PORT:-8082}${WS_HEALTH_PATH:-/actuator/health} | grep -q '\"status\"\\s*:\\s*\"UP\"'"] + # interval: 10s + # timeout: 5s + # retries: 30 + # start_period: 90s networks: - openisle-network @@ -151,8 +186,10 @@ services: ports: - "${FRONTEND_PORT:-3000}:3000" depends_on: - - springboot - - websocket-service + springboot: + condition: service_started + websocket-service: + condition: service_started networks: - openisle-network profiles: @@ -173,8 +210,10 @@ services: ports: - "${FRONTEND_SERVICE_PORT:-3001}:3000" depends_on: - - springboot - - websocket-service + springboot: + condition: service_started + websocket-service: + condition: service_started networks: - openisle-network profiles: diff --git a/docker/rabbitmq/conf/enabled_plugins b/docker/rabbitmq/conf/enabled_plugins new file mode 100644 index 000000000..5b44fea2e --- /dev/null +++ b/docker/rabbitmq/conf/enabled_plugins @@ -0,0 +1 @@ +[rabbitmq_management, rabbitmq_prometheus]. diff --git a/docker/rabbitmq/conf/rabbitmq.conf b/docker/rabbitmq/conf/rabbitmq.conf new file mode 100644 index 000000000..7734d03e0 --- /dev/null +++ b/docker/rabbitmq/conf/rabbitmq.conf @@ -0,0 +1,6 @@ +# 管理插件加载 definitions(仅空库时生效) +management.load_definitions = /etc/rabbitmq/definitions.json + +# (可选)禁用管理老式统计采集,转 Prometheus,避免弃用告警 +management_agent.disable_metrics_collector = true +management.disable_stats = true diff --git a/docker/rabbitmq/definitions.json b/docker/rabbitmq/definitions.json new file mode 100644 index 000000000..bf8fc561f --- /dev/null +++ b/docker/rabbitmq/definitions.json @@ -0,0 +1,31 @@ +{ + "users": [ + { "name": "nagisa", "password": "nagisa", "tags": "administrator" } + ], + "vhosts": [{ "name": "/" }], + "permissions": [ + { "user": "nagisa", "vhost": "/", "configure": ".*", "write": ".*", "read": ".*" } + ], + "queues": [ + { "name": "notifications-queue", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-0", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-1", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-2", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-3", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-4", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-5", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-6", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-7", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-8", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-9", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-a", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-b", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-c", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-d", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-e", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} }, + { "name": "notifications-queue-f", "vhost": "/", "durable": true, "auto_delete": false, "arguments": {} } + ], + "exchanges": [], + "bindings": [] + } + \ No newline at end of file From 201af061e4300bdc2596f2f58947d045010f9350 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 17:55:19 +0800 Subject: [PATCH 08/41] =?UTF-8?q?fix:=20=E7=AE=80=E5=8D=95=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 4 ++-- .../java/com/openisle/websocket/security/SecurityConfig.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.env.example b/.env.example index b89b03aff..e69054378 100644 --- a/.env.example +++ b/.env.example @@ -80,8 +80,8 @@ WEBPUSH_PRIVATE_KEY= LOG_LEVEL=INFO # === Frontend (Nuxt) === -NUXT_PUBLIC_API_BASE_URL=http://springboot:8080 -NUXT_PUBLIC_API_BASE_URL_SSR=http://localhost:8080 +NUXT_PUBLIC_API_BASE_URL=http://localhost:8080 +NUXT_PUBLIC_API_BASE_URL_SSR=http://springboot:8080 NUXT_PUBLIC_WEBSOCKET_URL=http://websocket_service:8082 NUXT_PUBLIC_WEBSITE_BASE_URL=http://localhost:3000 # 线上 & 本地均可使用 diff --git a/websocket_service/src/main/java/com/openisle/websocket/security/SecurityConfig.java b/websocket_service/src/main/java/com/openisle/websocket/security/SecurityConfig.java index 6d6da7faa..a0083ea6f 100644 --- a/websocket_service/src/main/java/com/openisle/websocket/security/SecurityConfig.java +++ b/websocket_service/src/main/java/com/openisle/websocket/security/SecurityConfig.java @@ -37,14 +37,14 @@ public class SecurityConfig { "http://localhost:8081", "http://localhost:8082", "http://localhost:3000", - "http://frontend_dev:3000", - "http://frontend_service:3000", "http://localhost:3001", "http://localhost", "http://30.211.97.238:3000", "http://30.211.97.238", "http://192.168.7.98", "http://192.168.7.98:3000", + "http://frontend_dev:3000", + "http://frontend_service:3000", websiteUrl, websiteUrl.replace("://www.", "://") )); From e9878487e8a8bb316d0b437bcc50476c59338624 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 18:08:35 +0800 Subject: [PATCH 09/41] =?UTF-8?q?fix:=20=E5=AE=B9=E5=99=A8=E5=86=85?= =?UTF-8?q?=E6=B5=81=E9=87=8F=E8=BD=AC=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 3 +- docker/docker-compose.yaml | 58 ++++++++++++++++++++++++++++++++++---- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/.env.example b/.env.example index e69054378..0fadfe5a0 100644 --- a/.env.example +++ b/.env.example @@ -81,8 +81,7 @@ LOG_LEVEL=INFO # === Frontend (Nuxt) === NUXT_PUBLIC_API_BASE_URL=http://localhost:8080 -NUXT_PUBLIC_API_BASE_URL_SSR=http://springboot:8080 -NUXT_PUBLIC_WEBSOCKET_URL=http://websocket_service:8082 +NUXT_PUBLIC_WEBSOCKET_URL=http://localhost:8082 NUXT_PUBLIC_WEBSITE_BASE_URL=http://localhost:3000 # 线上 & 本地均可使用 NUXT_PUBLIC_GOOGLE_CLIENT_ID=777830451304-nt8afkkap18gui4f9entcha99unal744.apps.googleusercontent.com diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 029c654e4..4e02f0904 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -14,7 +14,17 @@ services: networks: - openisle-network healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-u", "root", "-p$MYSQL_ROOT_PASSWORD"] + test: + [ + "CMD", + "mysqladmin", + "ping", + "-h", + "127.0.0.1", + "-u", + "root", + "-p$MYSQL_ROOT_PASSWORD", + ] interval: 5s timeout: 3s retries: 30 @@ -36,7 +46,7 @@ services: - cluster.blocks.create_index=false ulimits: memlock: { soft: -1, hard: -1 } - nofile: { soft: 65536, hard: 65536 } + nofile: { soft: 65536, hard: 65536 } volumes: - ./data:/usr/share/opensearch/data - ./snapshots:/snapshots @@ -45,7 +55,11 @@ services: - "${OPENSEARCH_METRICS_PORT:-9600}:9600" restart: unless-stopped healthcheck: - test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:9200/_cluster/health >/dev/null"] + test: + [ + "CMD-SHELL", + "curl -fsS http://127.0.0.1:9200/_cluster/health >/dev/null", + ] interval: 10s timeout: 5s retries: 30 @@ -65,7 +79,7 @@ services: - opensearch restart: unless-stopped networks: - - openisle-network + - openisle-network rabbitmq: image: rabbitmq:3.13-management @@ -90,7 +104,6 @@ services: networks: - openisle-network - redis: image: redis:7 container_name: openisle-redis @@ -219,6 +232,41 @@ services: profiles: - service + loopback_8080: + image: alpine/socat + container_name: loopback-8080 + # 监听“frontend_dev 容器自身的” 127.0.0.1:8080 → 转发到 springboot:8080 + command: ["-d","-d","-ly","TCP4-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork","TCP4:springboot:8080"] + depends_on: + springboot: + condition: service_started + network_mode: "service:frontend_dev" + profiles: ["dev"] + healthcheck: + test: ["CMD","sh","-c","nc -z 127.0.0.1 8080"] + interval: 5s + timeout: 3s + retries: 20 + start_period: 10s + + loopback_8082: + image: alpine/socat + container_name: loopback-8082 + # 监听 127.0.0.1:8082 → 转发到 websocket-service:8082(WS 纯 TCP 可直接过) + command: ["-d","-d","-ly","TCP4-LISTEN:8082,bind=127.0.0.1,reuseaddr,fork","TCP4:websocket-service:8082"] + depends_on: + websocket-service: + condition: service_started + network_mode: "service:frontend_dev" + profiles: ["dev"] + healthcheck: + test: ["CMD","sh","-c","nc -z 127.0.0.1 8082"] + interval: 5s + timeout: 3s + retries: 20 + start_period: 10s + + networks: openisle-network: driver: bridge From 2b6d7c5ab9384d5bd36cc28b1b03f99c65211218 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 18:12:55 +0800 Subject: [PATCH 10/41] =?UTF-8?q?fix:=20=E6=96=B0=E5=A2=9E=E5=A4=9A?= =?UTF-8?q?=E7=A7=8Durl=E4=BE=9B=E5=BC=80=E5=8F=91=E8=80=85=E9=80=89?= =?UTF-8?q?=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 0fadfe5a0..09c6104c2 100644 --- a/.env.example +++ b/.env.example @@ -80,8 +80,15 @@ WEBPUSH_PRIVATE_KEY= LOG_LEVEL=INFO # === Frontend (Nuxt) === -NUXT_PUBLIC_API_BASE_URL=http://localhost:8080 -NUXT_PUBLIC_WEBSOCKET_URL=http://localhost:8082 + +# NUXT_PUBLIC_API_BASE_URL=http://localhost:8080 +NUXT_PUBLIC_API_BASE_URL=https://www.open-isle.com +# NUXT_PUBLIC_API_BASE_URL=https://www.staging.open-isle.com + +# NUXT_PUBLIC_WEBSOCKET_URL=http://localhost:8082 +NUXT_PUBLIC_WEBSOCKET_URL=https://www.open-isle.com +# NUXT_PUBLIC_WEBSOCKET_URL=https://www.staging.open-isle.com + NUXT_PUBLIC_WEBSITE_BASE_URL=http://localhost:3000 # 线上 & 本地均可使用 NUXT_PUBLIC_GOOGLE_CLIENT_ID=777830451304-nt8afkkap18gui4f9entcha99unal744.apps.googleusercontent.com From b2a29913aa1a561596004c943e684dfe0cc771c3 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 19:11:18 +0800 Subject: [PATCH 11/41] =?UTF-8?q?feat:=20=E7=A7=BB=E5=8A=A8=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/db/init => docker/mysql}/init_script.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {backend/src/main/resources/db/init => docker/mysql}/init_script.sql (100%) diff --git a/backend/src/main/resources/db/init/init_script.sql b/docker/mysql/init_script.sql similarity index 100% rename from backend/src/main/resources/db/init/init_script.sql rename to docker/mysql/init_script.sql From 0cf81136913b0fdc2b19204b9ec1aa82c076b09b Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 19:14:48 +0800 Subject: [PATCH 12/41] =?UTF-8?q?Revert=20"feat:=20=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=BD=8D=E7=BD=AE"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit b2a29913aa1a561596004c943e684dfe0cc771c3. --- .../mysql => backend/src/main/resources/db/init}/init_script.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {docker/mysql => backend/src/main/resources/db/init}/init_script.sql (100%) diff --git a/docker/mysql/init_script.sql b/backend/src/main/resources/db/init/init_script.sql similarity index 100% rename from docker/mysql/init_script.sql rename to backend/src/main/resources/db/init/init_script.sql From 35c503eb6cb486f82af2f2110fe7a0dcc90d4676 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 19:26:02 +0800 Subject: [PATCH 13/41] =?UTF-8?q?feat:=20mysql=20=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 14 ++-- .../resources/db/init/00_init_db_and_user.sql | 17 ++++ .../src/main/resources/db/init/01_schema.sql | 57 +++++++++++++ .../main/resources/db/init/02_seed_data.sql | 36 +++++++++ .../main/resources/db/init/init_script.sql | 81 ------------------- docker/docker-compose.yaml | 29 +++++-- 6 files changed, 140 insertions(+), 94 deletions(-) create mode 100644 backend/src/main/resources/db/init/00_init_db_and_user.sql create mode 100644 backend/src/main/resources/db/init/01_schema.sql create mode 100644 backend/src/main/resources/db/init/02_seed_data.sql delete mode 100644 backend/src/main/resources/db/init/init_script.sql diff --git a/.env.example b/.env.example index 09c6104c2..d3466c33d 100644 --- a/.env.example +++ b/.env.example @@ -19,9 +19,9 @@ OPENSEARCH_HOST=opensearch # === Database Configuration === MYSQL_DATABASE=openisle -MYSQL_ROOT_PASSWORD= -MYSQL_USER= -MYSQL_PASSWORD= +MYSQL_ROOT_PASSWORD=openisle +MYSQL_USER=openisle +MYSQL_PASSWORD=openisle MYSQL_HOST=mysql # === Redis Configuration === @@ -81,12 +81,12 @@ LOG_LEVEL=INFO # === Frontend (Nuxt) === -# NUXT_PUBLIC_API_BASE_URL=http://localhost:8080 -NUXT_PUBLIC_API_BASE_URL=https://www.open-isle.com +NUXT_PUBLIC_API_BASE_URL=http://localhost:8080 +# NUXT_PUBLIC_API_BASE_URL=https://www.open-isle.com # NUXT_PUBLIC_API_BASE_URL=https://www.staging.open-isle.com -# NUXT_PUBLIC_WEBSOCKET_URL=http://localhost:8082 -NUXT_PUBLIC_WEBSOCKET_URL=https://www.open-isle.com +NUXT_PUBLIC_WEBSOCKET_URL=http://localhost:8082 +# NUXT_PUBLIC_WEBSOCKET_URL=https://www.open-isle.com # NUXT_PUBLIC_WEBSOCKET_URL=https://www.staging.open-isle.com NUXT_PUBLIC_WEBSITE_BASE_URL=http://localhost:3000 diff --git a/backend/src/main/resources/db/init/00_init_db_and_user.sql b/backend/src/main/resources/db/init/00_init_db_and_user.sql new file mode 100644 index 000000000..bbdceed25 --- /dev/null +++ b/backend/src/main/resources/db/init/00_init_db_and_user.sql @@ -0,0 +1,17 @@ +-- 统一字符集 +SET NAMES utf8mb4; +SET CHARACTER SET utf8mb4; +SET collation_connection = utf8mb4_0900_ai_ci; + +-- 创建数据库(如果不存在) +CREATE DATABASE IF NOT EXISTS `openisle` + CHARACTER SET utf8mb4 + COLLATE utf8mb4_0900_ai_ci; + +-- 创建业务账号(容器会基于环境变量自动创建;此处再兜底 + 幂等) +CREATE USER IF NOT EXISTS 'openisle'@'%' IDENTIFIED BY 'openisle'; +GRANT ALL PRIVILEGES ON `openisle`.* TO 'openisle'@'%'; +FLUSH PRIVILEGES; + +-- 切换到目标库 +USE `openisle`; diff --git a/backend/src/main/resources/db/init/01_schema.sql b/backend/src/main/resources/db/init/01_schema.sql new file mode 100644 index 000000000..0844e5799 --- /dev/null +++ b/backend/src/main/resources/db/init/01_schema.sql @@ -0,0 +1,57 @@ +USE `openisle`; + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- users 表 +CREATE TABLE IF NOT EXISTS `users` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `approved` bit(1) DEFAULT NULL, + `avatar` varchar(255) DEFAULT NULL, + `created_at` datetime(6) DEFAULT NULL, + `display_medal` varchar(255) DEFAULT NULL, + `email` varchar(255) NOT NULL, + `experience` int DEFAULT NULL, + `introduction` text, + `password` varchar(255) NOT NULL, + `password_reset_code` varchar(255) DEFAULT NULL, + `point` int DEFAULT NULL, + `register_reason` text, + `role` varchar(20) DEFAULT 'USER', + `username` varchar(50) NOT NULL, + `verification_code` varchar(255) DEFAULT NULL, + `verified` bit(1) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `UK_users_email` (`email`), + UNIQUE KEY `UK_users_username` (`username`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- categories 表 +CREATE TABLE IF NOT EXISTS `categories` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `description` text, + `icon` varchar(255) DEFAULT NULL, + `name` varchar(50) NOT NULL, + `small_icon` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `UK_categories_name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- tags 表(依赖 users.id 外键) +CREATE TABLE IF NOT EXISTS `tags` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `approved` bit(1) DEFAULT NULL, + `created_at` datetime(6) DEFAULT NULL, + `description` text, + `icon` varchar(255) DEFAULT NULL, + `name` varchar(50) NOT NULL, + `small_icon` varchar(255) DEFAULT NULL, + `creator_id` bigint DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `UK_tags_name` (`name`), + KEY `FK_tags_creator` (`creator_id`), + CONSTRAINT `FK_tags_creator` FOREIGN KEY (`creator_id`) REFERENCES `users` (`id`) + ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/backend/src/main/resources/db/init/02_seed_data.sql b/backend/src/main/resources/db/init/02_seed_data.sql new file mode 100644 index 000000000..d217be9a7 --- /dev/null +++ b/backend/src/main/resources/db/init/02_seed_data.sql @@ -0,0 +1,36 @@ +USE `openisle`; +SET FOREIGN_KEY_CHECKS = 0; + +-- 清空并灌入演示数据(幂等处理:先删再插) +DELETE FROM `tags`; +DELETE FROM `categories`; +DELETE FROM `users`; + +-- users(密码已是 bcrypt;账号:admin/user1/user2,明文 123321) +INSERT INTO `users` +(`id`,`approved`,`avatar`,`created_at`,`display_medal`,`email`,`experience`,`introduction`, + `password`,`password_reset_code`,`point`,`register_reason`,`role`,`username`,`verification_code`,`verified`) +VALUES +(1, b'1', '', '2025-09-01 16:08:17.426430', 'PIONEER', 'adminmail@openisle.com', 70, NULL, + '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 110, + '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'ADMIN', 'admin', NULL, b'1'), +(2, b'1', '', '2025-09-03 16:08:17.426430', 'PIONEER', 'usermail2@openisle.com', 70, NULL, + '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 110, + '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'USER', 'user1', NULL, b'1'), +(3, b'1', '', '2025-09-02 17:21:21.617666', 'PIONEER', 'usermail1@openisle.com', 40, NULL, + '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 40, + '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'USER', 'user2', NULL, b'1'); + +-- categories +INSERT INTO `categories` (`id`,`description`,`icon`,`name`,`small_icon`) VALUES +(1,'测试用分类1','1','测试用分类1',NULL), +(2,'测试用分类2','2','测试用分类2',NULL), +(3,'测试用分类3','3','测试用分类3',NULL); + +-- tags(此处不绑定 creator_id,避免外键顺序依赖;如需可填 1/2/3) +INSERT INTO `tags` (`id`,`approved`,`created_at`,`description`,`icon`,`name`,`small_icon`,`creator_id`) VALUES +(1,b'1','2025-09-02 10:51:56.000000','测试用标签1',NULL,'测试用标签1',NULL,NULL), +(2,b'1','2025-09-02 10:51:56.000000','测试用标签2',NULL,'测试用标签2',NULL,NULL), +(3,b'1','2025-09-02 10:51:56.000000','测试用标签3',NULL,'测试用标签3',NULL,NULL); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/backend/src/main/resources/db/init/init_script.sql b/backend/src/main/resources/db/init/init_script.sql deleted file mode 100644 index 3ea4bd2c1..000000000 --- a/backend/src/main/resources/db/init/init_script.sql +++ /dev/null @@ -1,81 +0,0 @@ --- 2025-09-02 --- 本地化开发,初始化脚本 --- 抽奖的时候奖品图片是必须的,把相关代码注释掉即可跳过check - --- 设置字符集和排序规则 -SET NAMES utf8; -SET CHARACTER SET utf8; -SET collation_connection = utf8_general_ci; - --- 创建 users 表(如果不存在) -CREATE TABLE IF NOT EXISTS `users` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `approved` bit(1) DEFAULT NULL, - `avatar` varchar(255) DEFAULT NULL, - `created_at` datetime(6) DEFAULT NULL, - `display_medal` varchar(255) DEFAULT NULL, - `email` varchar(255) NOT NULL, - `experience` int DEFAULT NULL, - `introduction` text, - `password` varchar(255) NOT NULL, - `password_reset_code` varchar(255) DEFAULT NULL, - `point` int DEFAULT NULL, - `register_reason` text, - `role` varchar(20) DEFAULT 'USER', - `username` varchar(50) NOT NULL, - `verification_code` varchar(255) DEFAULT NULL, - `verified` bit(1) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `UK_users_email` (`email`), - UNIQUE KEY `UK_users_username` (`username`) -); - --- 清空users表 -DELETE FROM `users`; --- 插入用户,两个普通用户,一个管理员 --- username:admin/user1/user2 password:123321 -INSERT INTO `users` (`id`, `approved`, `avatar`, `created_at`, `display_medal`, `email`, `experience`, `introduction`, `password`, `password_reset_code`, `point`, `register_reason`, `role`, `username`, `verification_code`, `verified`) VALUES - (1, b'1', '', '2025-09-01 16:08:17.426430', 'PIONEER', 'adminmail@openisle.com', 70, NULL, '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 110, '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'ADMIN', 'admin', NULL, b'1'), - (2, b'1', '', '2025-09-03 16:08:17.426430', 'PIONEER', 'usermail2@openisle.com', 70, NULL, '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 110, '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'USER', 'user1', NULL, b'1'), - (3, b'1', '', '2025-09-02 17:21:21.617666', 'PIONEER', 'usermail1@openisle.com', 40, NULL, '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 40, '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'USER', 'user2', NULL, b'1'); - --- 创建 tags 表(如果不存在) -CREATE TABLE IF NOT EXISTS `tags` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `approved` bit(1) DEFAULT NULL, - `created_at` datetime(6) DEFAULT NULL, - `description` text, - `icon` varchar(255) DEFAULT NULL, - `name` varchar(50) NOT NULL, - `small_icon` varchar(255) DEFAULT NULL, - `creator_id` bigint DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `UK_tags_name` (`name`), - KEY `FK_tags_creator` (`creator_id`), - CONSTRAINT `FK_tags_creator` FOREIGN KEY (`creator_id`) REFERENCES `users` (`id`) -); --- 清空tags表 -DELETE FROM `tags`; --- 插入标签,三个测试用标签 -INSERT INTO `tags` (`id`, `approved`, `created_at`, `description`, `icon`, `name`, `small_icon`, `creator_id`) VALUES - (1, b'1', '2025-09-02 10:51:56.000000', '测试用标签1', NULL, '测试用标签1', NULL, NULL), - (2, b'1', '2025-09-02 10:51:56.000000', '测试用标签2', NULL, '测试用标签2', NULL, NULL), - (3, b'1', '2025-09-02 10:51:56.000000', '测试用标签3', NULL, '测试用标签3', NULL, NULL); - --- 创建 categories 表(如果不存在) -CREATE TABLE IF NOT EXISTS `categories` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `description` text, - `icon` varchar(255) DEFAULT NULL, - `name` varchar(50) NOT NULL, - `small_icon` varchar(255) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `UK_categories_name` (`name`) -); --- 清空categories表 -DELETE FROM `categories`; --- 插入分类,三个测试用分类 -INSERT INTO `categories` (`id`, `description`, `icon`, `name`, `small_icon`) VALUES - (1, '测试用分类1', '1', '测试用分类1', NULL), - (2, '测试用分类2', '2', '测试用分类2', NULL), - (3, '测试用分类3', '3', '测试用分类3', NULL); \ No newline at end of file diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 4e02f0904..0746dcbe6 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -11,6 +11,10 @@ services: volumes: - mysql-data:/var/lib/mysql - ../backend/src/main/resources/db/init:/docker-entrypoint-initdb.d + command: > + --character-set-server=utf8mb4 + --collation-server=utf8mb4_0900_ai_ci + --default-time-zone=+80:00 networks: - openisle-network healthcheck: @@ -236,37 +240,50 @@ services: image: alpine/socat container_name: loopback-8080 # 监听“frontend_dev 容器自身的” 127.0.0.1:8080 → 转发到 springboot:8080 - command: ["-d","-d","-ly","TCP4-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork","TCP4:springboot:8080"] + command: + [ + "-d", + "-d", + "-ly", + "TCP4-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork", + "TCP4:springboot:8080", + ] depends_on: springboot: condition: service_started network_mode: "service:frontend_dev" profiles: ["dev"] healthcheck: - test: ["CMD","sh","-c","nc -z 127.0.0.1 8080"] + test: ["CMD", "sh", "-c", "nc -z 127.0.0.1 8080"] interval: 5s timeout: 3s retries: 20 start_period: 10s - + loopback_8082: image: alpine/socat container_name: loopback-8082 # 监听 127.0.0.1:8082 → 转发到 websocket-service:8082(WS 纯 TCP 可直接过) - command: ["-d","-d","-ly","TCP4-LISTEN:8082,bind=127.0.0.1,reuseaddr,fork","TCP4:websocket-service:8082"] + command: + [ + "-d", + "-d", + "-ly", + "TCP4-LISTEN:8082,bind=127.0.0.1,reuseaddr,fork", + "TCP4:websocket-service:8082", + ] depends_on: websocket-service: condition: service_started network_mode: "service:frontend_dev" profiles: ["dev"] healthcheck: - test: ["CMD","sh","-c","nc -z 127.0.0.1 8082"] + test: ["CMD", "sh", "-c", "nc -z 127.0.0.1 8082"] interval: 5s timeout: 3s retries: 20 start_period: 10s - networks: openisle-network: driver: bridge From 2f509cc2d815ebcb50cb333206545ac6009a48f7 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 19:27:24 +0800 Subject: [PATCH 14/41] =?UTF-8?q?feat:=20mysql=20=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 0746dcbe6..36f2392b3 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -14,7 +14,7 @@ services: command: > --character-set-server=utf8mb4 --collation-server=utf8mb4_0900_ai_ci - --default-time-zone=+80:00 + --default-time-zone=+08:00 networks: - openisle-network healthcheck: From 3d5cee6e6888db860903a61eaeedd5081d990ce6 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 19:41:04 +0800 Subject: [PATCH 15/41] =?UTF-8?q?feat:=20mysql=20=E4=B9=B1=E7=A0=81?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/db/init/00_init_db_and_user.sql | 4 --- .../src/main/resources/db/init/01_schema.sql | 5 +--- .../main/resources/db/init/02_seed_data.sql | 22 ++++------------ docker/docker-compose.yaml | 25 +++++++------------ docker/mysql/conf.d/charset.cnf | 10 ++++++++ 5 files changed, 25 insertions(+), 41 deletions(-) create mode 100644 docker/mysql/conf.d/charset.cnf diff --git a/backend/src/main/resources/db/init/00_init_db_and_user.sql b/backend/src/main/resources/db/init/00_init_db_and_user.sql index bbdceed25..d8cf198ef 100644 --- a/backend/src/main/resources/db/init/00_init_db_and_user.sql +++ b/backend/src/main/resources/db/init/00_init_db_and_user.sql @@ -1,17 +1,13 @@ --- 统一字符集 SET NAMES utf8mb4; SET CHARACTER SET utf8mb4; SET collation_connection = utf8mb4_0900_ai_ci; --- 创建数据库(如果不存在) CREATE DATABASE IF NOT EXISTS `openisle` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; --- 创建业务账号(容器会基于环境变量自动创建;此处再兜底 + 幂等) CREATE USER IF NOT EXISTS 'openisle'@'%' IDENTIFIED BY 'openisle'; GRANT ALL PRIVILEGES ON `openisle`.* TO 'openisle'@'%'; FLUSH PRIVILEGES; --- 切换到目标库 USE `openisle`; diff --git a/backend/src/main/resources/db/init/01_schema.sql b/backend/src/main/resources/db/init/01_schema.sql index 0844e5799..87e1e22da 100644 --- a/backend/src/main/resources/db/init/01_schema.sql +++ b/backend/src/main/resources/db/init/01_schema.sql @@ -1,9 +1,8 @@ USE `openisle`; - SET NAMES utf8mb4; + SET FOREIGN_KEY_CHECKS = 0; --- users 表 CREATE TABLE IF NOT EXISTS `users` ( `id` bigint NOT NULL AUTO_INCREMENT, `approved` bit(1) DEFAULT NULL, @@ -26,7 +25,6 @@ CREATE TABLE IF NOT EXISTS `users` ( UNIQUE KEY `UK_users_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; --- categories 表 CREATE TABLE IF NOT EXISTS `categories` ( `id` bigint NOT NULL AUTO_INCREMENT, `description` text, @@ -37,7 +35,6 @@ CREATE TABLE IF NOT EXISTS `categories` ( UNIQUE KEY `UK_categories_name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; --- tags 表(依赖 users.id 外键) CREATE TABLE IF NOT EXISTS `tags` ( `id` bigint NOT NULL AUTO_INCREMENT, `approved` bit(1) DEFAULT NULL, diff --git a/backend/src/main/resources/db/init/02_seed_data.sql b/backend/src/main/resources/db/init/02_seed_data.sql index d217be9a7..091635304 100644 --- a/backend/src/main/resources/db/init/02_seed_data.sql +++ b/backend/src/main/resources/db/init/02_seed_data.sql @@ -1,33 +1,21 @@ USE `openisle`; +SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; --- 清空并灌入演示数据(幂等处理:先删再插) DELETE FROM `tags`; DELETE FROM `categories`; DELETE FROM `users`; --- users(密码已是 bcrypt;账号:admin/user1/user2,明文 123321) -INSERT INTO `users` -(`id`,`approved`,`avatar`,`created_at`,`display_medal`,`email`,`experience`,`introduction`, - `password`,`password_reset_code`,`point`,`register_reason`,`role`,`username`,`verification_code`,`verified`) -VALUES -(1, b'1', '', '2025-09-01 16:08:17.426430', 'PIONEER', 'adminmail@openisle.com', 70, NULL, - '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 110, - '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'ADMIN', 'admin', NULL, b'1'), -(2, b'1', '', '2025-09-03 16:08:17.426430', 'PIONEER', 'usermail2@openisle.com', 70, NULL, - '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 110, - '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'USER', 'user1', NULL, b'1'), -(3, b'1', '', '2025-09-02 17:21:21.617666', 'PIONEER', 'usermail1@openisle.com', 40, NULL, - '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 40, - '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'USER', 'user2', NULL, b'1'); +INSERT INTO `users` (`id`,`approved`,`avatar`,`created_at`,`display_medal`,`email`,`experience`,`introduction`,`password`,`password_reset_code`,`point`,`register_reason`,`role`,`username`,`verification_code`,`verified`) VALUES +(1,b'1','', '2025-09-01 16:08:17.426430','PIONEER','adminmail@openisle.com',70,NULL,'$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe',NULL,110,'测试测试测试……','ADMIN','admin',NULL,b'1'), +(2,b'1','', '2025-09-03 16:08:17.426430','PIONEER','usermail2@openisle.com',70,NULL,'$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe',NULL,110,'测试测试测试……','USER','user1',NULL,b'1'), +(3,b'1','', '2025-09-02 17:21:21.617666','PIONEER','usermail1@openisle.com',40,NULL,'$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe',NULL,40,'测试测试测试……','USER','user2',NULL,b'1'); --- categories INSERT INTO `categories` (`id`,`description`,`icon`,`name`,`small_icon`) VALUES (1,'测试用分类1','1','测试用分类1',NULL), (2,'测试用分类2','2','测试用分类2',NULL), (3,'测试用分类3','3','测试用分类3',NULL); --- tags(此处不绑定 creator_id,避免外键顺序依赖;如需可填 1/2/3) INSERT INTO `tags` (`id`,`approved`,`created_at`,`description`,`icon`,`name`,`small_icon`,`creator_id`) VALUES (1,b'1','2025-09-02 10:51:56.000000','测试用标签1',NULL,'测试用标签1',NULL,NULL), (2,b'1','2025-09-02 10:51:56.000000','测试用标签2',NULL,'测试用标签2',NULL,NULL), diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 36f2392b3..d762df085 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -6,34 +6,27 @@ services: restart: always env_file: - ../.env - ports: - - "${MYSQL_PORT:-3306}:3306" - volumes: - - mysql-data:/var/lib/mysql - - ../backend/src/main/resources/db/init:/docker-entrypoint-initdb.d command: > --character-set-server=utf8mb4 --collation-server=utf8mb4_0900_ai_ci --default-time-zone=+08:00 + --skip-character-set-client-handshake + ports: + - "${MYSQL_PORT:-3306}:3306" + volumes: + - mysql-data:/var/lib/mysql + - ../backend/src/main/resources/db/init:/docker-entrypoint-initdb.d:ro + - ./mysql/conf.d:/etc/mysql/conf.d:ro networks: - openisle-network healthcheck: - test: - [ - "CMD", - "mysqladmin", - "ping", - "-h", - "127.0.0.1", - "-u", - "root", - "-p$MYSQL_ROOT_PASSWORD", - ] + test: ["CMD","mysqladmin","ping","-h","127.0.0.1","-u","root","-p$MYSQL_ROOT_PASSWORD"] interval: 5s timeout: 3s retries: 30 start_period: 20s + # OpenSearch Service opensearch: build: diff --git a/docker/mysql/conf.d/charset.cnf b/docker/mysql/conf.d/charset.cnf new file mode 100644 index 000000000..2464cce02 --- /dev/null +++ b/docker/mysql/conf.d/charset.cnf @@ -0,0 +1,10 @@ +[mysqld] +character-set-server = utf8mb4 +collation-server = utf8mb4_0900_ai_ci +skip-character-set-client-handshake + +[client] +default-character-set = utf8mb4 + +[mysql] +default-character-set = utf8mb4 From 73790d1992d9ff9675ccc6c9f8c8aa30f6727259 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 19:42:54 +0800 Subject: [PATCH 16/41] =?UTF-8?q?feat:=20healthy.=E6=A3=80=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.yaml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index d762df085..195b1e15d 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -143,13 +143,6 @@ services: command: > sh -c "apt-get update && apt-get install -y --no-install-recommends curl && mvn clean spring-boot:run -Dmaven.test.skip=true" - # healthcheck: - # test: ["CMD-SHELL", - # "curl -fsS http://127.0.0.1:${SERVER_PORT:-8080}${SPRING_HEALTH_PATH:-/actuator/health} | grep -q '\"status\"\\s*:\\s*\"UP\"'"] - # interval: 10s - # timeout: 5s - # retries: 30 - # start_period: 90s networks: - openisle-network @@ -173,13 +166,6 @@ services: command: > sh -c "apt-get update && apt-get install -y --no-install-recommends curl && mvn clean spring-boot:run -Dmaven.test.skip=true" - # healthcheck: - # test: ["CMD-SHELL", - # "curl -fsS http://127.0.0.1:${WEBSOCKET_PORT:-8082}${WS_HEALTH_PATH:-/actuator/health} | grep -q '\"status\"\\s*:\\s*\"UP\"'"] - # interval: 10s - # timeout: 5s - # retries: 30 - # start_period: 90s networks: - openisle-network From 287d52df10abcd425f362ab1f582b4317931108f Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 19:47:55 +0800 Subject: [PATCH 17/41] =?UTF-8?q?feat:=20healthy.=E6=A3=80=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.yaml | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 195b1e15d..d5ee840e8 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -137,12 +137,22 @@ services: rabbitmq: condition: service_started websocket-service: - condition: service_started + condition: service_healthy opensearch: condition: service_healthy command: > sh -c "apt-get update && apt-get install -y --no-install-recommends curl && mvn clean spring-boot:run -Dmaven.test.skip=true" + healthcheck: + test: + [ + "CMD-SHELL", + "curl -fsS http://127.0.0.1:${SERVER_PORT:-8080}${SPRING_HEALTH_PATH:-/actuator/health} || exit 1", + ] + interval: 10s + timeout: 5s + retries: 30 + start_period: 60s networks: - openisle-network @@ -166,6 +176,16 @@ services: command: > sh -c "apt-get update && apt-get install -y --no-install-recommends curl && mvn clean spring-boot:run -Dmaven.test.skip=true" + healthcheck: + test: + [ + "CMD-SHELL", + "curl -fsS http://127.0.0.1:${WEBSOCKET_PORT:-8082}${WS_HEALTH_PATH:-/actuator/health} || exit 1", + ] + interval: 10s + timeout: 5s + retries: 30 + start_period: 60s networks: - openisle-network @@ -183,9 +203,9 @@ services: - "${FRONTEND_PORT:-3000}:3000" depends_on: springboot: - condition: service_started + condition: service_healthy websocket-service: - condition: service_started + condition: service_healthy networks: - openisle-network profiles: @@ -207,9 +227,9 @@ services: - "${FRONTEND_SERVICE_PORT:-3001}:3000" depends_on: springboot: - condition: service_started + condition: service_healthy websocket-service: - condition: service_started + condition: service_healthy networks: - openisle-network profiles: @@ -229,7 +249,7 @@ services: ] depends_on: springboot: - condition: service_started + condition: service_healthy network_mode: "service:frontend_dev" profiles: ["dev"] healthcheck: @@ -253,7 +273,7 @@ services: ] depends_on: websocket-service: - condition: service_started + condition: service_healthy network_mode: "service:frontend_dev" profiles: ["dev"] healthcheck: From fffd335ebb7d603c2e6e92b850e1feb92b047f87 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 29 Sep 2025 19:54:37 +0800 Subject: [PATCH 18/41] =?UTF-8?q?fix:=20=E4=B8=A4=E4=B8=AAspringboot?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=8E=A2=E6=B4=BB=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/application.properties | 3 +++ websocket_service/src/main/resources/application.properties | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 4362668b3..81032349b 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -129,3 +129,6 @@ springdoc.info.description=OpenIsle Open API Documentation springdoc.info.version=0.0.1 springdoc.info.scheme=Bearer springdoc.info.header=Authorization + +management.endpoints.web.exposure.include=health,info +management.endpoint.health.probes.enabled=true \ No newline at end of file diff --git a/websocket_service/src/main/resources/application.properties b/websocket_service/src/main/resources/application.properties index 0bce91d31..87659cc08 100644 --- a/websocket_service/src/main/resources/application.properties +++ b/websocket_service/src/main/resources/application.properties @@ -19,4 +19,7 @@ logging.level.org.springframework.messaging=${MESSAGING_LOG_LEVEL:DEBUG} logging.level.org.springframework.web.socket=${WEBSOCKET_LOG_LEVEL:DEBUG} # 网站 URL 配置 -app.website-url=${WEBSITE_URL:https://www.open-isle.com} \ No newline at end of file +app.website-url=${WEBSITE_URL:https://www.open-isle.com} + +management.endpoints.web.exposure.include=health,info +management.endpoint.health.probes.enabled=true \ No newline at end of file From 5971700e8a32cb2323fc1e609e80e4de893273b2 Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 00:33:05 +0800 Subject: [PATCH 19/41] =?UTF-8?q?fix:=20=E6=96=B0=E5=A2=9E=E4=BE=9D?= =?UTF-8?q?=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/pom.xml | 4 ++++ websocket_service/pom.xml | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/backend/pom.xml b/backend/pom.xml index a0f1c9b7e..1908a5c1b 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -132,6 +132,10 @@ springdoc-openapi-starter-webmvc-api 2.2.0 + + org.springframework.boot + spring-boot-starter-actuator + org.opensearch.client diff --git a/websocket_service/pom.xml b/websocket_service/pom.xml index 37d29413c..4091615b2 100644 --- a/websocket_service/pom.xml +++ b/websocket_service/pom.xml @@ -51,10 +51,10 @@ lombok true - - - - + + org.springframework.boot + spring-boot-starter-actuator + org.springframework.boot spring-boot-starter-test From 24fe90cfc6bdcdadd5d72d44ebda4e96027fb27c Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 00:47:18 +0800 Subject: [PATCH 20/41] fix: change port --- websocket_service/src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/websocket_service/src/main/resources/application.properties b/websocket_service/src/main/resources/application.properties index 87659cc08..bd7de2ef9 100644 --- a/websocket_service/src/main/resources/application.properties +++ b/websocket_service/src/main/resources/application.properties @@ -1,4 +1,4 @@ -server.port=${SERVER_PORT:8082} +server.port=${WEBSOCKET_PORT:8082} # 服务器配置 spring.application.name=websocket-service From ca26b931dad7cd15954c948503aca315f0011832 Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 01:19:13 +0800 Subject: [PATCH 21/41] fix: use server port --- docker/docker-compose.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index d5ee840e8..1dfd9b1af 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -165,6 +165,7 @@ services: environment: WS_HEALTH_PATH: ${WS_HEALTH_PATH:-/actuator/health} WEBSOCKET_PORT: ${WEBSOCKET_PORT:-8082} + SERVER_PORT: ${WEBSOCKET_PORT:-8082} ports: - "${WEBSOCKET_PORT:-8082}:${WEBSOCKET_PORT:-8082}" volumes: From f8a2ee6ee95c38a183cd799087c863553a61aa4f Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 01:45:47 +0800 Subject: [PATCH 22/41] fix: use server port --- backend/src/main/java/com/openisle/config/SecurityConfig.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/main/java/com/openisle/config/SecurityConfig.java b/backend/src/main/java/com/openisle/config/SecurityConfig.java index b2d0da85e..4f9782cb3 100644 --- a/backend/src/main/java/com/openisle/config/SecurityConfig.java +++ b/backend/src/main/java/com/openisle/config/SecurityConfig.java @@ -179,6 +179,8 @@ public class SecurityConfig { .permitAll() .requestMatchers(HttpMethod.POST, "/api/point-goods") .permitAll() + .requestMatchers("/actuator/**") + .permitAll() .requestMatchers(HttpMethod.POST, "/api/categories/**") .hasAuthority("ADMIN") .requestMatchers(HttpMethod.POST, "/api/tags/**") From 28618c745239bb5f9bfd32e44536c86577c6ab14 Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 10:22:39 +0800 Subject: [PATCH 23/41] =?UTF-8?q?fix:=20springboot=20healthy=E6=A3=80?= =?UTF-8?q?=E6=B5=8B=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/openisle/config/SecurityConfig.java | 1 + backend/src/main/resources/db/init/02_seed_data.sql | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/openisle/config/SecurityConfig.java b/backend/src/main/java/com/openisle/config/SecurityConfig.java index 4f9782cb3..6a5dc8fb2 100644 --- a/backend/src/main/java/com/openisle/config/SecurityConfig.java +++ b/backend/src/main/java/com/openisle/config/SecurityConfig.java @@ -234,6 +234,7 @@ public class SecurityConfig { uri.startsWith("/api/channels") || uri.startsWith("/api/sitemap.xml") || uri.startsWith("/api/medals") || + uri.startsWith("/actuator") || uri.startsWith("/api/rss")); if (authHeader != null && authHeader.startsWith("Bearer ")) { diff --git a/backend/src/main/resources/db/init/02_seed_data.sql b/backend/src/main/resources/db/init/02_seed_data.sql index 091635304..53562803c 100644 --- a/backend/src/main/resources/db/init/02_seed_data.sql +++ b/backend/src/main/resources/db/init/02_seed_data.sql @@ -12,9 +12,9 @@ INSERT INTO `users` (`id`,`approved`,`avatar`,`created_at`,`display_medal`,`emai (3,b'1','', '2025-09-02 17:21:21.617666','PIONEER','usermail1@openisle.com',40,NULL,'$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe',NULL,40,'测试测试测试……','USER','user2',NULL,b'1'); INSERT INTO `categories` (`id`,`description`,`icon`,`name`,`small_icon`) VALUES -(1,'测试用分类1','1','测试用分类1',NULL), -(2,'测试用分类2','2','测试用分类2',NULL), -(3,'测试用分类3','3','测试用分类3',NULL); +(1,'测试用分类1','star','测试用分类1',NULL), +(2,'测试用分类2','star','测试用分类2',NULL), +(3,'测试用分类3','star','测试用分类3',NULL); INSERT INTO `tags` (`id`,`approved`,`created_at`,`description`,`icon`,`name`,`small_icon`,`creator_id`) VALUES (1,b'1','2025-09-02 10:51:56.000000','测试用标签1',NULL,'测试用标签1',NULL,NULL), From 7ce5de7f7c3c5d416095e1ffac05f561caaecdca Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 10:45:31 +0800 Subject: [PATCH 24/41] =?UTF-8?q?fix:=20=E8=87=AA=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/db/init/02_seed_data.sql | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/src/main/resources/db/init/02_seed_data.sql b/backend/src/main/resources/db/init/02_seed_data.sql index 53562803c..f3f375b7a 100644 --- a/backend/src/main/resources/db/init/02_seed_data.sql +++ b/backend/src/main/resources/db/init/02_seed_data.sql @@ -6,10 +6,12 @@ DELETE FROM `tags`; DELETE FROM `categories`; DELETE FROM `users`; -INSERT INTO `users` (`id`,`approved`,`avatar`,`created_at`,`display_medal`,`email`,`experience`,`introduction`,`password`,`password_reset_code`,`point`,`register_reason`,`role`,`username`,`verification_code`,`verified`) VALUES -(1,b'1','', '2025-09-01 16:08:17.426430','PIONEER','adminmail@openisle.com',70,NULL,'$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe',NULL,110,'测试测试测试……','ADMIN','admin',NULL,b'1'), -(2,b'1','', '2025-09-03 16:08:17.426430','PIONEER','usermail2@openisle.com',70,NULL,'$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe',NULL,110,'测试测试测试……','USER','user1',NULL,b'1'), -(3,b'1','', '2025-09-02 17:21:21.617666','PIONEER','usermail1@openisle.com',40,NULL,'$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe',NULL,40,'测试测试测试……','USER','user2',NULL,b'1'); +-- 插入用户,两个普通用户,一个管理员 +-- username:admin/user1/user2 password:123456 +INSERT INTO `users` (`id`, `approved`, `avatar`, `created_at`, `display_medal`, `email`, `experience`, `introduction`, `password`, `password_reset_code`, `point`, `register_reason`, `role`, `username`, `verification_code`, `verified`) VALUES +(1, b'1', 'https://openisle-1307107697.cos.ap-guangzhou.myqcloud.com/assert/image.png', '2025-09-01 16:08:17.426430', 'PIONEER', 'adminmail@openisle.com', 70, NULL, '$2a$10$x7HXjUyJTmrvqjnBlBQZH.vmfsC56NzTSWqQ6WqZqRjUO859EhviS', NULL, 110, '测试测试测试……', 'ADMIN', 'admin', NULL, b'1'), +(2, b'1', 'https://openisle-1307107697.cos.ap-guangzhou.myqcloud.com/assert/image.png', '2025-09-03 16:08:17.426430', 'PIONEER', 'usermail2@openisle.com', 70, NULL, '$2a$10$x7HXjUyJTmrvqjnBlBQZH.vmfsC56NzTSWqQ6WqZqRjUO859EhviS', NULL, 110, '测试测试测试……', 'USER', 'user1', NULL, b'1'), +(3, b'1', 'https://openisle-1307107697.cos.ap-guangzhou.myqcloud.com/assert/image.png', '2025-09-02 17:21:21.617666', 'PIONEER', 'usermail1@openisle.com', 40, NULL, '$2a$10$x7HXjUyJTmrvqjnBlBQZH.vmfsC56NzTSWqQ6WqZqRjUO859EhviS', NULL, 40, '测试测试测试……', 'USER', 'user2', NULL, b'1'); INSERT INTO `categories` (`id`,`description`,`icon`,`name`,`small_icon`) VALUES (1,'测试用分类1','star','测试用分类1',NULL), From d00dbbbd03db0344e4e682f359eb8965d02c2bef Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 13:51:43 +0800 Subject: [PATCH 25/41] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=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"] From 22b813e40b2d1940068d38594fa9b3ceaf332ee1 Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 14:16:10 +0800 Subject: [PATCH 26/41] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9yaml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.yaml | 56 ++++++++++++++------------------------ 1 file changed, 20 insertions(+), 36 deletions(-) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 9366e165a..dc946fc08 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -26,7 +26,6 @@ services: retries: 30 start_period: 20s - # OpenSearch Service opensearch: build: @@ -53,10 +52,8 @@ services: restart: unless-stopped healthcheck: test: - [ - "CMD-SHELL", - "curl -fsS http://127.0.0.1:9200/_cluster/health >/dev/null", - ] + - CMD-SHELL + - curl -fsS http://127.0.0.1:9200/_cluster/health >/dev/null interval: 10s timeout: 5s retries: 30 @@ -68,8 +65,8 @@ services: image: opensearchproject/opensearch-dashboards:3.0.0 container_name: os-dashboards environment: - - OPENSEARCH_HOSTS=["http://opensearch:9200"] - - DISABLE_SECURITY_DASHBOARDS_PLUGIN=true + OPENSEARCH_HOSTS: '["http://opensearch:9200"]' + DISABLE_SECURITY_DASHBOARDS_PLUGIN: "true" ports: - "${OPENSEARCH_DASHBOARDS_PORT:-5601}:5601" depends_on: @@ -83,7 +80,7 @@ services: container_name: openisle-rabbitmq restart: unless-stopped environment: - RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_VHOST:-/} + RABBITMQ_DEFAULT_VHOST: "${RABBITMQ_VHOST:-/}" ports: - "${RABBITMQ_PORT:-5672}:5672" - "${RABBITMQ_MANAGEMENT_PORT:-15672}:15672" @@ -144,11 +141,7 @@ services: sh -c "apt-get update && apt-get install -y --no-install-recommends curl && mvn clean spring-boot:run -Dmaven.test.skip=true" healthcheck: - test: - [ - "CMD-SHELL", - "curl -fsS http://127.0.0.1:${SERVER_PORT:-8080}${SPRING_HEALTH_PATH:-/actuator/health} || exit 1", - ] + test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:${SERVER_PORT:-8080}${SPRING_HEALTH_PATH:-/actuator/health} || exit 1"] interval: 10s timeout: 5s retries: 30 @@ -178,11 +171,7 @@ services: sh -c "apt-get update && apt-get install -y --no-install-recommends curl && mvn clean spring-boot:run -Dmaven.test.skip=true" healthcheck: - test: - [ - "CMD-SHELL", - "curl -fsS http://127.0.0.1:${WEBSOCKET_PORT:-8082}${WS_HEALTH_PATH:-/actuator/health} || exit 1", - ] + test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:${WEBSOCKET_PORT:-8082}${WS_HEALTH_PATH:-/actuator/health} || exit 1"] interval: 10s timeout: 5s retries: 30 @@ -212,16 +201,15 @@ services: profiles: - dev - frontend_service: + frontend_service: build: - context: .. # 仓库根目录(包含 frontend_nuxt/) + context: .. dockerfile: docker/frontend-service.Dockerfile args: - # 由 .env(或 --env-file)提供,默认 staging;正式环境脚本会传 production NUXT_ENV: ${NUXT_ENV:-staging} container_name: openisle-frontend env_file: - - ../.env # 或者在脚本里指定 .env.staging / .env.production + - ../.env ports: - "${FRONTEND_PORT:-3000}:3000" depends_on: @@ -236,13 +224,11 @@ services: container_name: loopback-8080 # 监听“frontend_dev 容器自身的” 127.0.0.1:8080 → 转发到 springboot:8080 command: - [ - "-d", - "-d", - "-ly", - "TCP4-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork", - "TCP4:springboot:8080", - ] + - -d + - -d + - -ly + - TCP4-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork + - TCP4:springboot:8080 depends_on: springboot: condition: service_healthy @@ -260,13 +246,11 @@ services: container_name: loopback-8082 # 监听 127.0.0.1:8082 → 转发到 websocket-service:8082(WS 纯 TCP 可直接过) command: - [ - "-d", - "-d", - "-ly", - "TCP4-LISTEN:8082,bind=127.0.0.1,reuseaddr,fork", - "TCP4:websocket-service:8082", - ] + - -d + - -d + - -ly + - TCP4-LISTEN:8082,bind=127.0.0.1,reuseaddr,fork + - TCP4:websocket-service:8082 depends_on: websocket-service: condition: service_healthy From 263f2deeb1c89642795d991dda4b48c6c597984a Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 14:32:30 +0800 Subject: [PATCH 27/41] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9yaml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index dc946fc08..04d7d2427 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -5,7 +5,7 @@ services: container_name: openisle-mysql restart: always env_file: - - ../.env + - ${ENV_FILE:-../.env} command: > --character-set-server=utf8mb4 --collation-server=utf8mb4_0900_ai_ci @@ -103,7 +103,7 @@ services: container_name: openisle-redis restart: unless-stopped env_file: - - ../.env + - ${ENV_FILE:-../.env} ports: - "${REDIS_PORT:-6379}:6379" volumes: @@ -111,13 +111,13 @@ services: networks: - openisle-network - # Java spring boot service + # Java spring boot service (开发便捷镜像,后续可换成打包镜像) springboot: image: maven:3.9-eclipse-temurin-17 container_name: openisle-springboot working_dir: /app env_file: - - ../.env + - ${ENV_FILE:-../.env} environment: SPRING_HEALTH_PATH: ${SPRING_HEALTH_PATH:-/actuator/health} SERVER_PORT: ${SERVER_PORT:-8080} @@ -154,7 +154,7 @@ services: container_name: openisle-websocket working_dir: /app env_file: - - ../.env + - ${ENV_FILE:-../.env} environment: WS_HEALTH_PATH: ${WS_HEALTH_PATH:-/actuator/health} WEBSOCKET_PORT: ${WEBSOCKET_PORT:-8082} @@ -184,7 +184,7 @@ services: container_name: openisle-frontend-dev working_dir: /app env_file: - - ../.env + - ${ENV_FILE:-../.env} command: sh -c "npm install && npm run dev" volumes: - ../frontend_nuxt:/app @@ -209,7 +209,7 @@ services: NUXT_ENV: ${NUXT_ENV:-staging} container_name: openisle-frontend env_file: - - ../.env + - ${ENV_FILE:-../.env} ports: - "${FRONTEND_PORT:-3000}:3000" depends_on: From 180c45bf2dc104e0881f7c0c7c0cae603be3b2ff Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 14:52:27 +0800 Subject: [PATCH 28/41] =?UTF-8?q?fix:=20=E7=AB=AF=E5=8F=A3=E9=80=82?= =?UTF-8?q?=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 04d7d2427..53f68ff10 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -12,7 +12,7 @@ services: --default-time-zone=+08:00 --skip-character-set-client-handshake ports: - - "${MYSQL_PORT:-3306}:3306" + - "${MYSQL_PORT:-3306}:${MYSQL_PORT:-3306}" volumes: - mysql-data:/var/lib/mysql - ../backend/src/main/resources/db/init:/docker-entrypoint-initdb.d:ro @@ -47,8 +47,8 @@ services: - ./data:/usr/share/opensearch/data - ./snapshots:/snapshots ports: - - "${OPENSEARCH_PORT:-9200}:9200" - - "${OPENSEARCH_METRICS_PORT:-9600}:9600" + - "${OPENSEARCH_PORT:-9200}:${OPENSEARCH_PORT:-9200}" + - "${OPENSEARCH_METRICS_PORT:-9600}:${OPENSEARCH_METRICS_PORT:-9600}" restart: unless-stopped healthcheck: test: @@ -68,7 +68,7 @@ services: OPENSEARCH_HOSTS: '["http://opensearch:9200"]' DISABLE_SECURITY_DASHBOARDS_PLUGIN: "true" ports: - - "${OPENSEARCH_DASHBOARDS_PORT:-5601}:5601" + - "${OPENSEARCH_DASHBOARDS_PORT:-5601}:${OPENSEARCH_DASHBOARDS_PORT:-5601}" depends_on: - opensearch restart: unless-stopped @@ -82,8 +82,8 @@ services: environment: RABBITMQ_DEFAULT_VHOST: "${RABBITMQ_VHOST:-/}" ports: - - "${RABBITMQ_PORT:-5672}:5672" - - "${RABBITMQ_MANAGEMENT_PORT:-15672}:15672" + - "${RABBITMQ_PORT:-5672}:${RABBITMQ_PORT:-5672}" + - "${RABBITMQ_MANAGEMENT_PORT:-15672}:${RABBITMQ_MANAGEMENT_PORT:-15672}" volumes: - rabbitmq-data:/var/lib/rabbitmq - ./rabbitmq/conf/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf:ro @@ -105,7 +105,7 @@ services: env_file: - ${ENV_FILE:-../.env} ports: - - "${REDIS_PORT:-6379}:6379" + - "${REDIS_PORT:-6379}:${REDIS_PORT:-6379}" volumes: - redis-data:/data networks: From b62b9c691f07bf9569247af9f22e8e4afd98672a Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 14:54:57 +0800 Subject: [PATCH 29/41] =?UTF-8?q?fix:=20healthy=20check=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 53f68ff10..33f80912b 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -53,7 +53,7 @@ services: healthcheck: test: - CMD-SHELL - - curl -fsS http://127.0.0.1:9200/_cluster/health >/dev/null + - curl -fsS http://127.0.0.1:${OPENSEARCH_PORT:-9200}/_cluster/health >/dev/null interval: 10s timeout: 5s retries: 30 From 2457efd11d3aad395cc57d6fb91771c1bf83348f Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 15:02:36 +0800 Subject: [PATCH 30/41] =?UTF-8?q?Revert=20"fix:=20healthy=20check=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit b62b9c691f07bf9569247af9f22e8e4afd98672a. --- docker/docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 33f80912b..53f68ff10 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -53,7 +53,7 @@ services: healthcheck: test: - CMD-SHELL - - curl -fsS http://127.0.0.1:${OPENSEARCH_PORT:-9200}/_cluster/health >/dev/null + - curl -fsS http://127.0.0.1:9200/_cluster/health >/dev/null interval: 10s timeout: 5s retries: 30 From 9dc9ca9bd8ea0cf4f56b99464688ef3f6ef7662a Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 15:02:40 +0800 Subject: [PATCH 31/41] =?UTF-8?q?Revert=20"fix:=20=E7=AB=AF=E5=8F=A3?= =?UTF-8?q?=E9=80=82=E9=85=8D"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 180c45bf2dc104e0881f7c0c7c0cae603be3b2ff. --- docker/docker-compose.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 53f68ff10..04d7d2427 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -12,7 +12,7 @@ services: --default-time-zone=+08:00 --skip-character-set-client-handshake ports: - - "${MYSQL_PORT:-3306}:${MYSQL_PORT:-3306}" + - "${MYSQL_PORT:-3306}:3306" volumes: - mysql-data:/var/lib/mysql - ../backend/src/main/resources/db/init:/docker-entrypoint-initdb.d:ro @@ -47,8 +47,8 @@ services: - ./data:/usr/share/opensearch/data - ./snapshots:/snapshots ports: - - "${OPENSEARCH_PORT:-9200}:${OPENSEARCH_PORT:-9200}" - - "${OPENSEARCH_METRICS_PORT:-9600}:${OPENSEARCH_METRICS_PORT:-9600}" + - "${OPENSEARCH_PORT:-9200}:9200" + - "${OPENSEARCH_METRICS_PORT:-9600}:9600" restart: unless-stopped healthcheck: test: @@ -68,7 +68,7 @@ services: OPENSEARCH_HOSTS: '["http://opensearch:9200"]' DISABLE_SECURITY_DASHBOARDS_PLUGIN: "true" ports: - - "${OPENSEARCH_DASHBOARDS_PORT:-5601}:${OPENSEARCH_DASHBOARDS_PORT:-5601}" + - "${OPENSEARCH_DASHBOARDS_PORT:-5601}:5601" depends_on: - opensearch restart: unless-stopped @@ -82,8 +82,8 @@ services: environment: RABBITMQ_DEFAULT_VHOST: "${RABBITMQ_VHOST:-/}" ports: - - "${RABBITMQ_PORT:-5672}:${RABBITMQ_PORT:-5672}" - - "${RABBITMQ_MANAGEMENT_PORT:-15672}:${RABBITMQ_MANAGEMENT_PORT:-15672}" + - "${RABBITMQ_PORT:-5672}:5672" + - "${RABBITMQ_MANAGEMENT_PORT:-15672}:15672" volumes: - rabbitmq-data:/var/lib/rabbitmq - ./rabbitmq/conf/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf:ro @@ -105,7 +105,7 @@ services: env_file: - ${ENV_FILE:-../.env} ports: - - "${REDIS_PORT:-6379}:${REDIS_PORT:-6379}" + - "${REDIS_PORT:-6379}:6379" volumes: - redis-data:/data networks: From 181ac7bc8f0061dfe96774c6ee5bbfc2a1f43039 Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 15:09:59 +0800 Subject: [PATCH 32/41] =?UTF-8?q?fix:=20=E5=AE=B9=E5=99=A8port=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 04d7d2427..e016c8a6a 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -121,6 +121,10 @@ services: environment: SPRING_HEALTH_PATH: ${SPRING_HEALTH_PATH:-/actuator/health} SERVER_PORT: ${SERVER_PORT:-8080} + RABBITMQ_PORT: 5672 + OPENSEARCH_PORT: 9200 + MYSQL_PORT: 3306 + REDIS_PORT: 6379 ports: - "${SERVER_PORT:-8080}:${SERVER_PORT:-8080}" volumes: @@ -159,6 +163,7 @@ services: WS_HEALTH_PATH: ${WS_HEALTH_PATH:-/actuator/health} WEBSOCKET_PORT: ${WEBSOCKET_PORT:-8082} SERVER_PORT: ${WEBSOCKET_PORT:-8082} + RABBITMQ_PORT: 5672 ports: - "${WEBSOCKET_PORT:-8082}:${WEBSOCKET_PORT:-8082}" volumes: From 18a6953ff794b29ef9a9b1b6986094a346fa00c0 Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 15:15:11 +0800 Subject: [PATCH 33/41] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3opensearch?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index e016c8a6a..78318a754 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -28,6 +28,7 @@ services: # OpenSearch Service opensearch: + user: "1000:1000" build: context: . dockerfile: opensearch.Dockerfile From b49e20d0109927d763211c1778b729eb4c4a9d53 Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 21:33:14 +0800 Subject: [PATCH 34/41] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E5=90=8D=E3=80=81=E5=8F=98=E9=87=8F=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/deploy_staging.sh | 57 ++++++++++++++++++++++++++++++++++++++ docker/docker-compose.yaml | 35 ++++++++++++++--------- 2 files changed, 79 insertions(+), 13 deletions(-) create mode 100644 deploy/deploy_staging.sh diff --git a/deploy/deploy_staging.sh b/deploy/deploy_staging.sh new file mode 100644 index 000000000..f2d623259 --- /dev/null +++ b/deploy/deploy_staging.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -euo pipefail + +# 可用法: +# ./deploy-staging.sh +# ./deploy-staging.sh feature/docker +deploy_branch="${1:-feature/docker}" + +repo_dir="/opt/openisle/OpenIsle-staging" +compose_file="${repo_dir}/docker/docker-compose.yaml" +# 使用仓库根目录的 .env(CI 预先写好),也可以改成绝对路径 +env_file="${repo_dir}/.env" +project="openisle_staging" + +echo "👉 Enter repo..." +cd "$repo_dir" + +echo "👉 Syncing code & switching to branch: $deploy_branch" +git fetch --all --prune +git checkout -B "$deploy_branch" "origin/$deploy_branch" +git reset --hard "origin/$deploy_branch" + +echo "👉 Ensuring env file: $env_file" +if [ ! -f "$env_file" ]; then + echo "❌ ${env_file} not found. Create it based on .env.example (with staging domains)." + exit 1 +fi + +export COMPOSE_PROJECT_NAME="$project" +# 供 compose 内各 service 的 env_file 使用 +export ENV_FILE="$env_file" + +echo "👉 Validate compose..." +docker compose -f "$compose_file" --env-file "$env_file" config >/dev/null + +echo "👉 Pull base images (for image-based services)..." +docker compose -f "$compose_file" --env-file "$env_file" pull --ignore-pull-failures + +echo "👉 Build images (staging)..." +# 前端 + OpenSearch 都是自建镜像;--pull 更新其基础镜像 +docker compose -f "$compose_file" --env-file "$env_file" \ + build --pull \ + --build-arg NUXT_ENV=staging \ + frontend_service opensearch + +echo "👉 Recreate & start all target services (no dev profile)..." +docker compose -f "$compose_file" --env-file "$env_file" \ + up -d --force-recreate --remove-orphans \ + mysql redis rabbitmq opensearch dashboards websocket-service springboot frontend_service + +echo "👉 Current status:" +docker compose -f "$compose_file" --env-file "$env_file" ps + +echo "👉 Pruning dangling images..." +docker image prune -f + +echo "✅ Staging stack deployed at $(date)" \ No newline at end of file diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 78318a754..ade5aeaaf 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -2,7 +2,7 @@ services: # MySQL service mysql: image: mysql:8.0 - container_name: openisle-mysql + container_name: ${COMPOSE_PROJECT_NAME}-openisle-mysql restart: always env_file: - ${ENV_FILE:-../.env} @@ -32,7 +32,7 @@ services: build: context: . dockerfile: opensearch.Dockerfile - container_name: opensearch + container_name: ${COMPOSE_PROJECT_NAME}-opensearch environment: - cluster.name=os-single - node.name=os-node-1 @@ -45,8 +45,8 @@ services: memlock: { soft: -1, hard: -1 } nofile: { soft: 65536, hard: 65536 } volumes: - - ./data:/usr/share/opensearch/data - - ./snapshots:/snapshots + - ${OPENSEARCH_DATA_DIR:-./data}:/usr/share/opensearch/data + - ${OPENSEARCH_SNAPSHOT_DIR:-./snapshots}:/snapshots ports: - "${OPENSEARCH_PORT:-9200}:9200" - "${OPENSEARCH_METRICS_PORT:-9600}:9600" @@ -64,7 +64,7 @@ services: dashboards: image: opensearchproject/opensearch-dashboards:3.0.0 - container_name: os-dashboards + container_name: ${COMPOSE_PROJECT_NAME}-os-dashboards environment: OPENSEARCH_HOSTS: '["http://opensearch:9200"]' DISABLE_SECURITY_DASHBOARDS_PLUGIN: "true" @@ -78,7 +78,7 @@ services: rabbitmq: image: rabbitmq:3.13-management - container_name: openisle-rabbitmq + container_name: ${COMPOSE_PROJECT_NAME}-openisle-rabbitmq restart: unless-stopped environment: RABBITMQ_DEFAULT_VHOST: "${RABBITMQ_VHOST:-/}" @@ -101,7 +101,7 @@ services: redis: image: redis:7 - container_name: openisle-redis + container_name: ${COMPOSE_PROJECT_NAME}-openisle-redis restart: unless-stopped env_file: - ${ENV_FILE:-../.env} @@ -115,7 +115,7 @@ services: # Java spring boot service (开发便捷镜像,后续可换成打包镜像) springboot: image: maven:3.9-eclipse-temurin-17 - container_name: openisle-springboot + container_name: ${COMPOSE_PROJECT_NAME}-openisle-springboot working_dir: /app env_file: - ${ENV_FILE:-../.env} @@ -156,7 +156,7 @@ services: websocket-service: image: maven:3.9-eclipse-temurin-17 - container_name: openisle-websocket + container_name: ${COMPOSE_PROJECT_NAME}-openisle-websocket working_dir: /app env_file: - ${ENV_FILE:-../.env} @@ -187,7 +187,7 @@ services: frontend_dev: image: node:20 - container_name: openisle-frontend-dev + container_name: ${COMPOSE_PROJECT_NAME}-openisle-frontend-dev working_dir: /app env_file: - ${ENV_FILE:-../.env} @@ -213,7 +213,7 @@ services: dockerfile: docker/frontend-service.Dockerfile args: NUXT_ENV: ${NUXT_ENV:-staging} - container_name: openisle-frontend + container_name: ${COMPOSE_PROJECT_NAME}-openisle-frontend env_file: - ${ENV_FILE:-../.env} ports: @@ -227,7 +227,7 @@ services: loopback_8080: image: alpine/socat - container_name: loopback-8080 + container_name: ${COMPOSE_PROJECT_NAME}-loopback-8080 # 监听“frontend_dev 容器自身的” 127.0.0.1:8080 → 转发到 springboot:8080 command: - -d @@ -249,7 +249,7 @@ services: loopback_8082: image: alpine/socat - container_name: loopback-8082 + container_name: ${COMPOSE_PROJECT_NAME}-loopback-8082 # 监听 127.0.0.1:8082 → 转发到 websocket-service:8082(WS 纯 TCP 可直接过) command: - -d @@ -271,14 +271,23 @@ services: networks: openisle-network: + name: "${COMPOSE_PROJECT_NAME}_net" driver: bridge volumes: mysql-data: + name: "${COMPOSE_PROJECT_NAME}_mysql-data" maven-repo: + name: "${COMPOSE_PROJECT_NAME}_maven-repo" redis-data: + name: "${COMPOSE_PROJECT_NAME}_redis-data" rabbitmq-data: + name: "${COMPOSE_PROJECT_NAME}_rabbitmq-data" websocket-maven-repo: + name: "${COMPOSE_PROJECT_NAME}_websocket-maven-repo" frontend-node-modules: + name: "${COMPOSE_PROJECT_NAME}_frontend-node-modules" frontend-service-node-modules: + name: "${COMPOSE_PROJECT_NAME}_frontend-service-node-modules" frontend-static: + name: "${COMPOSE_PROJECT_NAME}_frontend-static" From a0ea63700f3e616b19e95083de62ae971b13876e Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 21:34:30 +0800 Subject: [PATCH 35/41] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/deploy.sh | 50 +++++++++++++++++++++++++++++++++++ deploy/deploy_staging.sh | 57 ---------------------------------------- 2 files changed, 50 insertions(+), 57 deletions(-) create mode 100644 deploy/deploy.sh delete mode 100644 deploy/deploy_staging.sh diff --git a/deploy/deploy.sh b/deploy/deploy.sh new file mode 100644 index 000000000..25b9a3979 --- /dev/null +++ b/deploy/deploy.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +# 用法: +# ./deploy.sh staging +# ./deploy.sh prod +env="${1:-staging}" # staging | prod +project="openisle_${env}" + +repo_dir="/opt/openisle/OpenIsle-${env}" +compose_file="${repo_dir}/docker/docker-compose.yaml" +env_file="${repo_dir}/.env.${env}" + +echo "👉 Enter repo..." +cd "$repo_dir" + +echo "👉 Sync & checkout..." +git fetch --all --prune +git checkout -B "main" "origin/main" +git reset --hard "origin/main" + +echo "👉 Ensure env file: $env_file" +[ -f "$env_file" ] || { echo "❌ $env_file missing"; exit 1; } + +export COMPOSE_PROJECT_NAME="$project" +export ENV_FILE="$env_file" + +echo "👉 Validate compose..." +docker compose -f "$compose_file" --env-file "$env_file" config >/dev/null + +echo "👉 Pull images..." +docker compose -f "$compose_file" --env-file "$env_file" pull --ignore-pull-failures + +echo "👉 Build custom images..." +docker compose -f "$compose_file" --env-file "$env_file" \ + build --pull \ + --build-arg NUXT_ENV="$env" \ + frontend_service opensearch + +echo "👉 Up services..." +docker compose -f "$compose_file" --env-file "$env_file" up -d --force-recreate --remove-orphans \ + mysql redis rabbitmq opensearch dashboards websocket-service springboot frontend_service + +echo "👉 Status" +docker compose -f "$compose_file" --env-file "$env_file" ps + +echo "👉 Prune dangling images" +docker image prune -f + +echo "✅ ${env} stack deployed at $(date)" diff --git a/deploy/deploy_staging.sh b/deploy/deploy_staging.sh deleted file mode 100644 index f2d623259..000000000 --- a/deploy/deploy_staging.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# 可用法: -# ./deploy-staging.sh -# ./deploy-staging.sh feature/docker -deploy_branch="${1:-feature/docker}" - -repo_dir="/opt/openisle/OpenIsle-staging" -compose_file="${repo_dir}/docker/docker-compose.yaml" -# 使用仓库根目录的 .env(CI 预先写好),也可以改成绝对路径 -env_file="${repo_dir}/.env" -project="openisle_staging" - -echo "👉 Enter repo..." -cd "$repo_dir" - -echo "👉 Syncing code & switching to branch: $deploy_branch" -git fetch --all --prune -git checkout -B "$deploy_branch" "origin/$deploy_branch" -git reset --hard "origin/$deploy_branch" - -echo "👉 Ensuring env file: $env_file" -if [ ! -f "$env_file" ]; then - echo "❌ ${env_file} not found. Create it based on .env.example (with staging domains)." - exit 1 -fi - -export COMPOSE_PROJECT_NAME="$project" -# 供 compose 内各 service 的 env_file 使用 -export ENV_FILE="$env_file" - -echo "👉 Validate compose..." -docker compose -f "$compose_file" --env-file "$env_file" config >/dev/null - -echo "👉 Pull base images (for image-based services)..." -docker compose -f "$compose_file" --env-file "$env_file" pull --ignore-pull-failures - -echo "👉 Build images (staging)..." -# 前端 + OpenSearch 都是自建镜像;--pull 更新其基础镜像 -docker compose -f "$compose_file" --env-file "$env_file" \ - build --pull \ - --build-arg NUXT_ENV=staging \ - frontend_service opensearch - -echo "👉 Recreate & start all target services (no dev profile)..." -docker compose -f "$compose_file" --env-file "$env_file" \ - up -d --force-recreate --remove-orphans \ - mysql redis rabbitmq opensearch dashboards websocket-service springboot frontend_service - -echo "👉 Current status:" -docker compose -f "$compose_file" --env-file "$env_file" ps - -echo "👉 Pruning dangling images..." -docker image prune -f - -echo "✅ Staging stack deployed at $(date)" \ No newline at end of file From a6dd2bfbc234916b80d6be2138fa92ab057616e0 Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 30 Sep 2025 21:40:14 +0800 Subject: [PATCH 36/41] =?UTF-8?q?Revert=20"fix:=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=90=8D"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit a0ea63700f3e616b19e95083de62ae971b13876e. --- deploy/deploy.sh | 50 ----------------------------------- deploy/deploy_staging.sh | 57 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 50 deletions(-) delete mode 100644 deploy/deploy.sh create mode 100644 deploy/deploy_staging.sh diff --git a/deploy/deploy.sh b/deploy/deploy.sh deleted file mode 100644 index 25b9a3979..000000000 --- a/deploy/deploy.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# 用法: -# ./deploy.sh staging -# ./deploy.sh prod -env="${1:-staging}" # staging | prod -project="openisle_${env}" - -repo_dir="/opt/openisle/OpenIsle-${env}" -compose_file="${repo_dir}/docker/docker-compose.yaml" -env_file="${repo_dir}/.env.${env}" - -echo "👉 Enter repo..." -cd "$repo_dir" - -echo "👉 Sync & checkout..." -git fetch --all --prune -git checkout -B "main" "origin/main" -git reset --hard "origin/main" - -echo "👉 Ensure env file: $env_file" -[ -f "$env_file" ] || { echo "❌ $env_file missing"; exit 1; } - -export COMPOSE_PROJECT_NAME="$project" -export ENV_FILE="$env_file" - -echo "👉 Validate compose..." -docker compose -f "$compose_file" --env-file "$env_file" config >/dev/null - -echo "👉 Pull images..." -docker compose -f "$compose_file" --env-file "$env_file" pull --ignore-pull-failures - -echo "👉 Build custom images..." -docker compose -f "$compose_file" --env-file "$env_file" \ - build --pull \ - --build-arg NUXT_ENV="$env" \ - frontend_service opensearch - -echo "👉 Up services..." -docker compose -f "$compose_file" --env-file "$env_file" up -d --force-recreate --remove-orphans \ - mysql redis rabbitmq opensearch dashboards websocket-service springboot frontend_service - -echo "👉 Status" -docker compose -f "$compose_file" --env-file "$env_file" ps - -echo "👉 Prune dangling images" -docker image prune -f - -echo "✅ ${env} stack deployed at $(date)" diff --git a/deploy/deploy_staging.sh b/deploy/deploy_staging.sh new file mode 100644 index 000000000..f2d623259 --- /dev/null +++ b/deploy/deploy_staging.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -euo pipefail + +# 可用法: +# ./deploy-staging.sh +# ./deploy-staging.sh feature/docker +deploy_branch="${1:-feature/docker}" + +repo_dir="/opt/openisle/OpenIsle-staging" +compose_file="${repo_dir}/docker/docker-compose.yaml" +# 使用仓库根目录的 .env(CI 预先写好),也可以改成绝对路径 +env_file="${repo_dir}/.env" +project="openisle_staging" + +echo "👉 Enter repo..." +cd "$repo_dir" + +echo "👉 Syncing code & switching to branch: $deploy_branch" +git fetch --all --prune +git checkout -B "$deploy_branch" "origin/$deploy_branch" +git reset --hard "origin/$deploy_branch" + +echo "👉 Ensuring env file: $env_file" +if [ ! -f "$env_file" ]; then + echo "❌ ${env_file} not found. Create it based on .env.example (with staging domains)." + exit 1 +fi + +export COMPOSE_PROJECT_NAME="$project" +# 供 compose 内各 service 的 env_file 使用 +export ENV_FILE="$env_file" + +echo "👉 Validate compose..." +docker compose -f "$compose_file" --env-file "$env_file" config >/dev/null + +echo "👉 Pull base images (for image-based services)..." +docker compose -f "$compose_file" --env-file "$env_file" pull --ignore-pull-failures + +echo "👉 Build images (staging)..." +# 前端 + OpenSearch 都是自建镜像;--pull 更新其基础镜像 +docker compose -f "$compose_file" --env-file "$env_file" \ + build --pull \ + --build-arg NUXT_ENV=staging \ + frontend_service opensearch + +echo "👉 Recreate & start all target services (no dev profile)..." +docker compose -f "$compose_file" --env-file "$env_file" \ + up -d --force-recreate --remove-orphans \ + mysql redis rabbitmq opensearch dashboards websocket-service springboot frontend_service + +echo "👉 Current status:" +docker compose -f "$compose_file" --env-file "$env_file" ps + +echo "👉 Pruning dangling images..." +docker image prune -f + +echo "✅ Staging stack deployed at $(date)" \ No newline at end of file From 25a7f1e13814e4ca3650fd199d0fe76a57996628 Mon Sep 17 00:00:00 2001 From: tim Date: Wed, 1 Oct 2025 11:35:02 +0800 Subject: [PATCH 37/41] fix: add deploy --- deploy/deploy.sh | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 deploy/deploy.sh diff --git a/deploy/deploy.sh b/deploy/deploy.sh new file mode 100644 index 000000000..f2d623259 --- /dev/null +++ b/deploy/deploy.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -euo pipefail + +# 可用法: +# ./deploy-staging.sh +# ./deploy-staging.sh feature/docker +deploy_branch="${1:-feature/docker}" + +repo_dir="/opt/openisle/OpenIsle-staging" +compose_file="${repo_dir}/docker/docker-compose.yaml" +# 使用仓库根目录的 .env(CI 预先写好),也可以改成绝对路径 +env_file="${repo_dir}/.env" +project="openisle_staging" + +echo "👉 Enter repo..." +cd "$repo_dir" + +echo "👉 Syncing code & switching to branch: $deploy_branch" +git fetch --all --prune +git checkout -B "$deploy_branch" "origin/$deploy_branch" +git reset --hard "origin/$deploy_branch" + +echo "👉 Ensuring env file: $env_file" +if [ ! -f "$env_file" ]; then + echo "❌ ${env_file} not found. Create it based on .env.example (with staging domains)." + exit 1 +fi + +export COMPOSE_PROJECT_NAME="$project" +# 供 compose 内各 service 的 env_file 使用 +export ENV_FILE="$env_file" + +echo "👉 Validate compose..." +docker compose -f "$compose_file" --env-file "$env_file" config >/dev/null + +echo "👉 Pull base images (for image-based services)..." +docker compose -f "$compose_file" --env-file "$env_file" pull --ignore-pull-failures + +echo "👉 Build images (staging)..." +# 前端 + OpenSearch 都是自建镜像;--pull 更新其基础镜像 +docker compose -f "$compose_file" --env-file "$env_file" \ + build --pull \ + --build-arg NUXT_ENV=staging \ + frontend_service opensearch + +echo "👉 Recreate & start all target services (no dev profile)..." +docker compose -f "$compose_file" --env-file "$env_file" \ + up -d --force-recreate --remove-orphans \ + mysql redis rabbitmq opensearch dashboards websocket-service springboot frontend_service + +echo "👉 Current status:" +docker compose -f "$compose_file" --env-file "$env_file" ps + +echo "👉 Pruning dangling images..." +docker image prune -f + +echo "✅ Staging stack deployed at $(date)" \ No newline at end of file From a2b0cd1a476f230fd99ee737aa519c65ec3dbf4a Mon Sep 17 00:00:00 2001 From: tim Date: Wed, 1 Oct 2025 11:36:55 +0800 Subject: [PATCH 38/41] =?UTF-8?q?fix:=20=E6=96=B0=E5=A2=9Edeploy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/deploy.sh | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/deploy/deploy.sh b/deploy/deploy.sh index f2d623259..d371dfec6 100644 --- a/deploy/deploy.sh +++ b/deploy/deploy.sh @@ -2,15 +2,14 @@ set -euo pipefail # 可用法: -# ./deploy-staging.sh -# ./deploy-staging.sh feature/docker +# ./deploy.sh +# ./deploy.sh feature/docker deploy_branch="${1:-feature/docker}" -repo_dir="/opt/openisle/OpenIsle-staging" +repo_dir="/opt/openisle/OpenIsle" compose_file="${repo_dir}/docker/docker-compose.yaml" -# 使用仓库根目录的 .env(CI 预先写好),也可以改成绝对路径 env_file="${repo_dir}/.env" -project="openisle_staging" +project="openisle" echo "👉 Enter repo..." cd "$repo_dir" @@ -22,7 +21,7 @@ git reset --hard "origin/$deploy_branch" echo "👉 Ensuring env file: $env_file" if [ ! -f "$env_file" ]; then - echo "❌ ${env_file} not found. Create it based on .env.example (with staging domains)." + echo "❌ ${env_file} not found. Create it based on .env.example (with domains)." exit 1 fi @@ -36,11 +35,11 @@ docker compose -f "$compose_file" --env-file "$env_file" config >/dev/null echo "👉 Pull base images (for image-based services)..." docker compose -f "$compose_file" --env-file "$env_file" pull --ignore-pull-failures -echo "👉 Build images (staging)..." +echo "👉 Build images ..." # 前端 + OpenSearch 都是自建镜像;--pull 更新其基础镜像 docker compose -f "$compose_file" --env-file "$env_file" \ build --pull \ - --build-arg NUXT_ENV=staging \ + --build-arg NUXT_ENV=production \ frontend_service opensearch echo "👉 Recreate & start all target services (no dev profile)..." @@ -54,4 +53,4 @@ docker compose -f "$compose_file" --env-file "$env_file" ps echo "👉 Pruning dangling images..." docker image prune -f -echo "✅ Staging stack deployed at $(date)" \ No newline at end of file +echo "✅ Stack deployed at $(date)" \ No newline at end of file From 12bc4058567dea5f6b25e66a631ec743e6343ff1 Mon Sep 17 00:00:00 2001 From: tim Date: Wed, 1 Oct 2025 15:36:18 +0800 Subject: [PATCH 39/41] =?UTF-8?q?fix:=20=E6=97=B6=E5=8C=BA=E9=99=90?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index ade5aeaaf..d3bcab39f 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -114,6 +114,7 @@ services: # Java spring boot service (开发便捷镜像,后续可换成打包镜像) springboot: + TZ: "Asia/Shanghai" image: maven:3.9-eclipse-temurin-17 container_name: ${COMPOSE_PROJECT_NAME}-openisle-springboot working_dir: /app From 6f9570dc95b48d5042b6abc068d28bb3e765d0bb Mon Sep 17 00:00:00 2001 From: tim Date: Wed, 1 Oct 2025 15:38:12 +0800 Subject: [PATCH 40/41] =?UTF-8?q?fix:=20=E6=97=B6=E5=8C=BA=E9=99=90?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index d3bcab39f..9211cd37a 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -114,13 +114,13 @@ services: # Java spring boot service (开发便捷镜像,后续可换成打包镜像) springboot: - TZ: "Asia/Shanghai" image: maven:3.9-eclipse-temurin-17 container_name: ${COMPOSE_PROJECT_NAME}-openisle-springboot working_dir: /app env_file: - ${ENV_FILE:-../.env} environment: + TZ: "Asia/Shanghai" SPRING_HEALTH_PATH: ${SPRING_HEALTH_PATH:-/actuator/health} SERVER_PORT: ${SERVER_PORT:-8080} RABBITMQ_PORT: 5672 From 737157e557292fcfed42a8ac11990c372d6c9eef Mon Sep 17 00:00:00 2001 From: tim Date: Wed, 1 Oct 2025 16:08:53 +0800 Subject: [PATCH 41/41] fix: add timezone --- docker/docker-compose.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 9211cd37a..a1307b786 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -127,6 +127,7 @@ services: OPENSEARCH_PORT: 9200 MYSQL_PORT: 3306 REDIS_PORT: 6379 + JAVA_OPTS: "-Duser.timezone=Asia/Shanghai" ports: - "${SERVER_PORT:-8080}:${SERVER_PORT:-8080}" volumes: