diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..e4b9040 --- /dev/null +++ b/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -e +cd "$(dirname "$0")/source_clean" + +VERSION=$(cat ../VERSION) +echo "🔨 Building CloudSearch v${VERSION}..." + +docker build -t cloudsearch-app:v${VERSION} -t cloudsearch-app:latest . + +echo "✅ Built: cloudsearch-app:v${VERSION} + cloudsearch-app:latest" +echo " Run: docker-compose up -d app" diff --git a/docker-compose.yml b/docker-compose.yml index e7b3be0..5f0d0d6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,13 +1,16 @@ -# CloudSearch v2.3.0 — 单容器部署(全功能集成) +# CloudSearch — single source of truth: ./VERSION +# 注意: 此 compose 用于参考/文档。实际部署使用 docker run 以兼容 1Panel Redis。 + networks: - cloudsearch-net: + cloudsearch-network: driver: bridge volumes: admin-data: app-data: + external: true + name: cloudsearch_app-data pansou-data: - redis-data: x-logging: &default-logging driver: json-file @@ -16,29 +19,31 @@ x-logging: &default-logging max-file: "10" services: - # ============ Redis ============ - redis: - container_name: CloudSearch_Redis - image: redis:7-alpine - command: redis-server --save 60 1 --appendonly yes - volumes: - - redis-data:/data - restart: always + pansou: + container_name: CloudSearch_PanSou + image: ghcr.io/fish2018/pansou-web:latest networks: - - cloudsearch-net + cloudsearch-network: + aliases: + - pansou + environment: + - DOMAIN=${DOMAIN:-localhost} + - CACHE_TTL=60 + volumes: + - pansou-data:/app/data + restart: always logging: *default-logging - # ============ 全功能主应用 ============ app: container_name: CloudSearch_App - image: cloudsearch-app:v0.3.0 + image: cloudsearch-app:latest ports: - "9527:9527" environment: - NODE_ENV=production - CORS_ORIGIN=http://jp-cs.timaa.cn - - JWT_SECRET=u-_1wBd1IlQNYwZ9l5P1838x2fdsp0DI-BUhMouJeIg - - ADMIN_PASSWORD=0nL5kLhMIJ1121PYmQb25A + - JWT_SECRET=u-_1wB...JeIg + - ADMIN_PASSWORD=0nL5kL...b25A - PANSOU_URL=http://pansou:80 - DB_PATH=/data/database.sqlite - REDIS_URL=redis://:redis_GbR7XZ@1Panel-redis-aDp3:6379 @@ -46,19 +51,18 @@ services: - TRANSFER_CONFIG_PATH=/data/transfer_config.json - TZ=Asia/Shanghai - APP_VERSION_FILE=/data/VERSION - - FEISHU_APP_ID=${FEISHU_APP_ID:-} - - FEISHU_APP_SECRET=${FEISHU_APP_SECRET:-} - - FEISHU_VERIFY_TOKEN=${FEISHU_VERIFY_TOKEN:-} - - FEISHU_WEBHOOK_URL=${FEISHU_WEBHOOK_URL:-} - - TMDB_API_KEY=${TMDB_API_KEY:-} volumes: - - app-data:/data + - cloudsearch_app-data:/data - ./uploads:/app/uploads + - ./VERSION:/app/VERSION - ./icons:/app/dist/frontend/admin/icons - - ./VERSION:/data/VERSION depends_on: - - # ============ 管理后台 (功能开关) ============ + - pansou + restart: always + networks: + - cloudsearch-network + logging: *default-logging + admin: container_name: CloudSearch_Admin image: cloudsearch-admin:v0.1.0 @@ -66,54 +70,11 @@ services: - "127.0.0.1:9531:9531" environment: - ADMIN_PORT=9531 - - ADMIN_PASSWORD=0nL5kLhMIJ1121PYmQb25A + - ADMIN_PASSWORD=0nL5kL...b25A - ADMIN_DB_PATH=/data/admin_flags.sqlite volumes: - admin-data:/data restart: always networks: - - cloudsearch-net + - cloudsearch-network logging: *default-logging - - pansou: - condition: service_started - redis: - condition: service_started - restart: always - networks: - - cloudsearch-net - logging: *default-logging - - - # ============ 管理后台 (功能开关) ============ - admin: - container_name: CloudSearch_Admin - image: cloudsearch-admin:v0.1.0 - ports: - - "127.0.0.1:9531:9531" - environment: - - ADMIN_PORT=9531 - - ADMIN_PASSWORD=0nL5kLhMIJ1121PYmQb25A - - ADMIN_DB_PATH=/data/admin_flags.sqlite - volumes: - - admin-data:/data - restart: always - networks: - - cloudsearch-net - logging: *default-logging - - pansou: - container_name: CloudSearch_PanSou - image: ghcr.io/fish2018/pansou-web:latest - expose: - - "80" - environment: - - DOMAIN=${DOMAIN:-localhost} - - CACHE_TTL=60 - volumes: - - pansou-data:/app/data - restart: always - networks: - - cloudsearch-net - logging: *default-logging - diff --git a/source_clean/Dockerfile b/source_clean/Dockerfile index 9e9812a..a52366b 100644 --- a/source_clean/Dockerfile +++ b/source_clean/Dockerfile @@ -24,6 +24,8 @@ COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/dist ./dist COPY --from=builder /app/package.json ./ COPY frontend/ ./dist/frontend/ +# VERSION baked into image — single source of truth +COPY VERSION /app/VERSION EXPOSE 9527 ENTRYPOINT ["dumb-init", "--"] CMD ["node", "dist/main.js"] diff --git a/source_clean/VERSION b/source_clean/VERSION new file mode 100644 index 0000000..0d91a54 --- /dev/null +++ b/source_clean/VERSION @@ -0,0 +1 @@ +0.3.0 diff --git a/source_clean/package.json b/source_clean/package.json index 0538429..413b73f 100755 --- a/source_clean/package.json +++ b/source_clean/package.json @@ -1,6 +1,6 @@ { "name": "cloudsearch-backend", - "version": "2.0.26", + "version": "0.0.0", "private": true, "scripts": { "dev": "tsx watch src/main.ts", diff --git a/source_clean/src/main.ts b/source_clean/src/main.ts index 9f8030c..2f59132 100755 --- a/source_clean/src/main.ts +++ b/source_clean/src/main.ts @@ -4,7 +4,7 @@ import cors from 'cors'; import helmet from 'helmet'; import morgan from 'morgan'; import config from './config'; -const { version } = require('../package.json'); +import { VERSION as version } from "./version"; import { getDb } from './database/database'; import { connectRedis, disconnectRedis, reconnectRedis, testRedisConnection } from './middleware/cache'; import rateLimiter from './middleware/rate-limit'; diff --git a/source_clean/src/version.ts b/source_clean/src/version.ts new file mode 100644 index 0000000..8d9cfbc --- /dev/null +++ b/source_clean/src/version.ts @@ -0,0 +1,27 @@ +import fs from 'fs'; + +/** + * Read version from file. Order: + * 1. APP_VERSION_FILE env var (e.g. /data/VERSION from mounted volume) + * 2. /app/VERSION (built into Docker image) + * 3. Fallback hardcoded default + */ +function readVersionFromFile(): string { + const paths = [ + process.env.APP_VERSION_FILE, // from env + '/app/VERSION', // built-in fallback + ].filter(Boolean) as string[]; + + for (const p of paths) { + try { + const content = fs.readFileSync(p, 'utf-8').trim(); + if (content) return content; + } catch { + // file doesn't exist, try next + } + } + + return '0.0.0'; // ultimate fallback — should never happen +} + +export const VERSION = readVersionFromFile();