fix: 增加docker一键部署一键测试

master
Lxy 3 months ago
parent a35459e3dc
commit 5410a0b8ab

@ -1,54 +1,69 @@
# 构建阶段 # ============================================
# A股智投分析平台 - 后端服务 Dockerfile
# 多阶段构建,生产环境优化
# ============================================
# 阶段1构建阶段
FROM node:20-alpine AS builder FROM node:20-alpine AS builder
WORKDIR /app WORKDIR /app
# 安装必要依赖
RUN apk add --no-cache openssl
# 复制 package.json 和 package-lock.json # 复制 package.json 和 package-lock.json
COPY package*.json ./ COPY package*.json ./
COPY prisma ./prisma/ COPY prisma ./prisma/
# 安装依赖 # 安装所有依赖(包括开发依赖)
RUN npm ci RUN npm ci
# 复制源代码
COPY . .
# 生成 Prisma Client # 生成 Prisma Client
RUN npx prisma generate RUN npx prisma generate
# 构建 TypeScript # 复制源代码
COPY . .
# 编译 TypeScript
RUN npm run build RUN npm run build
# 生产阶段 # ============================================
# 阶段2生产阶段
FROM node:20-alpine FROM node:20-alpine
WORKDIR /app WORKDIR /app
# 安装必要的系统依赖 # 安装必要的系统依赖
RUN apk add --no-cache openssl RUN apk add --no-cache openssl wget
# 创建日志目录
RUN mkdir -p logs
# 复制 package.json 和 package-lock.json # 复制 package.json 和 package-lock.json
COPY package*.json ./ COPY package*.json ./
COPY prisma ./prisma/ COPY prisma ./prisma/
# 安装生产依赖 # 安装生产依赖(不包含开发依赖)
RUN npm ci --only=production RUN npm ci --only=production && npm cache clean --force
# 生成 Prisma Client针对生产环境 # 重新生成 Prisma Client针对生产环境
RUN npx prisma generate RUN npx prisma generate
# 从构建阶段复制编译后的代码 # 从构建阶段复制编译后的代码
COPY --from=builder /app/dist ./dist COPY --from=builder /app/dist ./dist
# 创建日志目录 # 创建非 root 用户
RUN mkdir -p logs RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
RUN chown -R nodejs:nodejs /app/logs
USER nodejs
# 暴露端口 # 暴露端口
EXPOSE 3000 EXPOSE 3000
# 健康检查 # 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/v1/health || exit 1 CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/v1/health || exit 1
# 启动命令 # 启动命令
CMD ["node", "dist/app.js"] CMD ["node", "dist/app.js"]

@ -1,56 +1,43 @@
version: '3.8' version: '3.8'
services: services:
# 后端应用 # MySQL 8.0 数据库
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- PORT=3000
- DATABASE_URL=mysql://root:rootpass@mysql:3306/aguzhitou
- REDIS_URL=redis://redis:6379
- JWT_SECRET=${JWT_SECRET:-your-secret-key-min-32-characters-long}
- JWT_EXPIRES_IN=7d
- LOG_LEVEL=info
- AKSHARE_URL=http://akshare:8000
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
volumes:
- ./logs:/app/logs
restart: always
networks:
- aguzhitou-network
# MySQL 数据库
mysql: mysql:
image: mysql:8.0 image: mysql:8.0
container_name: aguzhitou-mysql
environment: environment:
- MYSQL_ROOT_PASSWORD=rootpass MYSQL_ROOT_PASSWORD: 1qazse42W3
- MYSQL_DATABASE=aguzhitou MYSQL_DATABASE: aguzhitou
- MYSQL_CHARSET=utf8mb4 MYSQL_CHARSET: utf8mb4
- MYSQL_COLLATION=utf8mb4_unicode_ci MYSQL_COLLATION: utf8mb4_unicode_ci
TZ: Asia/Shanghai
volumes: volumes:
- mysql_data:/var/lib/mysql - mysql_data:/var/lib/mysql
- ./init-scripts:/docker-entrypoint-initdb.d:ro
ports: ports:
- "3306:3306" - "3306:3306"
healthcheck: healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-prootpass"] test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p1qazse42W3"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 retries: 5
start_period: 30s
restart: always restart: always
networks: networks:
- aguzhitou-network - aguzhitou-network
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci command: >
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
--innodb_buffer_pool_size=512M
--max_connections=200
--wait_timeout=28800
--interactive_timeout=28800
# Redis 缓存 # Redis 7 缓存
redis: redis:
image: redis:7-alpine image: redis:7-alpine
container_name: aguzhitou-redis
volumes: volumes:
- redis_data:/data - redis_data:/data
ports: ports:
@ -64,19 +51,61 @@ services:
networks: networks:
- aguzhitou-network - aguzhitou-network
# 后端应用
app:
build:
context: .
dockerfile: Dockerfile
container_name: aguzhitou-app
environment:
NODE_ENV: production
PORT: 3000
DATABASE_URL: mysql://root:1qazse42W3@mysql:3306/aguzhitou
REDIS_URL: redis://redis:6379
JWT_SECRET: aguzhitou-docker-secret-key-2024-prod-only-min-32-characters
JWT_EXPIRES_IN: 7d
LOG_LEVEL: info
AKSHARE_URL: http://localhost:8000
ports:
- "3000:3000"
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
volumes:
- ./logs:/app/logs
restart: always
networks:
- aguzhitou-network
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/api/v1/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# AKShare 数据服务(可选) # AKShare 数据服务(可选)
akshare: akshare:
image: registry.cn-shanghai.aliyuncs.com/akshare/akshare:latest image: registry.cn-shanghai.aliyuncs.com/akshare/akshare:latest
container_name: aguzhitou-akshare
ports: ports:
- "8000:8000" - "8000:8000"
restart: always restart: always
networks: networks:
- aguzhitou-network - aguzhitou-network
profiles:
- with-akshare
volumes: volumes:
mysql_data: mysql_data:
driver: local
redis_data: redis_data:
driver: local
networks: networks:
aguzhitou-network: aguzhitou-network:
driver: bridge driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16

Loading…
Cancel
Save