[fix]: 恢复缺失的 deploy/local/compose.yml 和 nginx.conf 文件

playwright E2E 测试发现:
1. compose.yml 和 nginx.conf 从 deploy/local/ 目录被意外删除
2. Docker 项目 'local' 的配置文件丢失,容器重启后无法重建
3. 添加 deploy/local/data/ 到 .gitignore 防止 Docker 运行时数据被提交

Playwright 测试验证结果:
- /fl/login 登录页加载正常 (HTTP 200)
- admin/admin 登录成功,跳转到后台页面
- 无 JS 控制台错误
- 静态资源(CSS/favicon)加载正常
- API /health 健康检查正常
This commit is contained in:
chengkai3
2026-06-30 16:35:45 +08:00
parent 5c60fd5c78
commit c9247778f7
9 changed files with 287 additions and 0 deletions
+14
View File
@@ -60,3 +60,17 @@ deploy/pro-deploy/data/**
!deploy/pro-deploy/data/minio/.gitkeep !deploy/pro-deploy/data/minio/.gitkeep
!deploy/pro-deploy/data/postgres/.gitkeep !deploy/pro-deploy/data/postgres/.gitkeep
!deploy/pro-deploy/data/redis/.gitkeep !deploy/pro-deploy/data/redis/.gitkeep
deploy/local/data/**
!deploy/local/data/app/
!deploy/local/data/app/celery/
!deploy/local/data/minio/
!deploy/local/data/postgres/
!deploy/local/data/redis/
!deploy/local/data/.gitkeep
!deploy/local/data/app/.gitkeep
!deploy/local/data/app/celery/.gitkeep
!deploy/local/data/app/wine/
!deploy/local/data/app/wine/**
!deploy/local/data/minio/.gitkeep
!deploy/local/data/postgres/.gitkeep
!deploy/local/data/redis/.gitkeep
+227
View File
@@ -0,0 +1,227 @@
services:
proxy:
image: docker.m.daocloud.io/library/nginx:1.27-alpine
container_name: ${COMPOSE_PROJECT_NAME}-proxy
ports:
- "${PROXY_PORT}:3000"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- web
restart: unless-stopped
db:
image: ${POSTGRES_IMAGE}
container_name: ${COMPOSE_PROJECT_NAME}-db
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
PGDATA: /var/lib/postgresql/data/pgdata
ports:
- "${POSTGRES_PORT}:5432"
volumes:
- ./data/postgres:/var/lib/postgresql/data
restart: unless-stopped
redis:
image: ${REDIS_IMAGE}
container_name: ${COMPOSE_PROJECT_NAME}-redis
ports:
- "${REDIS_PORT}:6379"
volumes:
- ./data/redis:/data
command:
- redis-server
- --appendonly
- "yes"
- --requirepass
- ${REDIS_PASSWORD}
- --save
- ""
- --stop-writes-on-bgsave-error
- "no"
restart: unless-stopped
minio:
image: ${MINIO_IMAGE}
container_name: ${COMPOSE_PROJECT_NAME}-minio
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}
ports:
- "${MINIO_API_PORT}:9000"
- "${MINIO_CONSOLE_PORT}:9001"
volumes:
- ./data/minio:/data
restart: unless-stopped
minio-init:
image: ${MINIO_MC_IMAGE}
container_name: ${COMPOSE_PROJECT_NAME}-minio-init
depends_on:
- minio
entrypoint: /bin/sh
command:
- -c
- >
until mc alias set local "$${MINIO_ENDPOINT}" "$${MINIO_ACCESS_KEY}" "$${MINIO_SECRET_KEY}"; do
sleep 1;
done;
mc mb -p "local/$${MINIO_BUCKET}" || true;
environment:
MINIO_ENDPOINT: ${MINIO_ENDPOINT}
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
MINIO_BUCKET: ${MINIO_BUCKET}
restart: "no"
api:
image: fquiz-worker:local
container_name: ${COMPOSE_PROJECT_NAME}-api
depends_on:
- db
- redis
- minio
- minio-init
environment:
API_HOST: 0.0.0.0
API_PORT: 8000
DB_HOST: db
DB_PORT: 5432
DB_NAME: fquiz
DB_USERNAME: ${DB_USERNAME}
DB_PASSWORD: ${DB_PASSWORD}
DB_SCHEMA: public
USER_USERNAME_COLUMN: username
USER_PASSWORD_COLUMN: password_hash
USER_STATUS_COLUMN: status
DATABASE_URL: postgresql+psycopg://${DB_USERNAME}:${DB_PASSWORD}@db:5432/fquiz
MINIO_ENABLED: "true"
MINIO_ENDPOINT: http://minio:9000
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
MINIO_BUCKET: ${MINIO_BUCKET}
MINIO_REGION: us-east-1
CELERY_BROKER_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
CELERY_RESULT_BACKEND: redis://:${REDIS_PASSWORD}@redis:6379/1
CELERY_TIMEZONE: Asia/Shanghai
FLOWER_BASIC_AUTH: ${FLOWER_BASIC_AUTH}
FLOWER_API_BASE_URL: http://flower:5555
FLOWER_API_TIMEOUT_SECONDS: 10
JWT_SECRET_KEY: ${JWT_SECRET_KEY}
ACCESS_TOKEN_EXPIRE_MINUTES: ${ACCESS_TOKEN_EXPIRE_MINUTES}
REFRESH_TOKEN_EXPIRE_DAYS: ${REFRESH_TOKEN_EXPIRE_DAYS}
REFRESH_COOKIE_SECURE: "false"
REFRESH_COOKIE_SAMESITE: lax
API_CORS_ORIGINS: http://localhost:3000,http://127.0.0.1:3000
WORKER_REGISTRY_TTL_SECONDS: 90
WINE_BINARY_PATH: wine
WINE_ALLOWED_ROOT: /app/data/wine
WINE_DEFAULT_TIMEOUT_SECONDS: 300
WINE_MAX_TIMEOUT_SECONDS: 1800
FILE_VFS_ROOT: /app/data/vfs
ports:
- "${API_PORT}:8000"
volumes:
- ./data/app:/app/data
restart: unless-stopped
celery-worker:
image: fquiz-worker:local
container_name: ${COMPOSE_PROJECT_NAME}-celery-worker
command:
- celery
- -A
- app.core.celery_app.celery_app
- worker
- --loglevel=${CELERY_LOG_LEVEL}
- --concurrency=${CELERY_WORKER_CONCURRENCY}
- --queues=${CELERY_WORKER_QUEUES}
depends_on:
- api
- redis
environment:
DB_HOST: db
DB_PORT: 5432
DB_NAME: fquiz
DB_USERNAME: ${DB_USERNAME}
DB_PASSWORD: ${DB_PASSWORD}
DB_SCHEMA: public
DATABASE_URL: postgresql+psycopg://${DB_USERNAME}:${DB_PASSWORD}@db:5432/fquiz
CELERY_BROKER_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
CELERY_RESULT_BACKEND: redis://:${REDIS_PASSWORD}@redis:6379/1
CELERY_TIMEZONE: Asia/Shanghai
MINIO_ENABLED: "true"
MINIO_ENDPOINT: http://minio:9000
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
MINIO_BUCKET: ${MINIO_BUCKET}
MINIO_REGION: us-east-1
WINE_BINARY_PATH: wine
WINE_ALLOWED_ROOT: /app/data/wine
WINE_DEFAULT_TIMEOUT_SECONDS: 300
WINE_MAX_TIMEOUT_SECONDS: 1800
volumes:
- ./data/app:/app/data
restart: unless-stopped
celery-beat:
image: fquiz-worker:local
container_name: ${COMPOSE_PROJECT_NAME}-celery-beat
command:
- celery
- -A
- app.core.celery_app.celery_app
- beat
- --loglevel=${CELERY_LOG_LEVEL}
- --schedule=/app/data/celery/beat-schedule
depends_on:
- api
- redis
environment:
DB_HOST: db
DB_PORT: 5432
DB_NAME: fquiz
DATABASE_URL: postgresql+psycopg://${DB_USERNAME}:${DB_PASSWORD}@db:5432/fquiz
CELERY_BROKER_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
CELERY_RESULT_BACKEND: redis://:${REDIS_PASSWORD}@redis:6379/1
CELERY_TIMEZONE: Asia/Shanghai
volumes:
- ./data/app:/app/data
restart: unless-stopped
flower:
image: fquiz-worker:local
container_name: ${COMPOSE_PROJECT_NAME}-flower
command:
- celery
- -A
- app.core.celery_app.celery_app
- flower
- --address=0.0.0.0
- --port=5555
- --persistent=False
- --basic-auth=${FLOWER_BASIC_AUTH}
depends_on:
- redis
environment:
CELERY_BROKER_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
CELERY_RESULT_BACKEND: redis://:${REDIS_PASSWORD}@redis:6379/1
CELERY_TIMEZONE: Asia/Shanghai
FLOWER_BASIC_AUTH: ${FLOWER_BASIC_AUTH:-admin:admin}
ports:
- "${FLOWER_PORT}:5555"
restart: unless-stopped
web:
image: fquiz-web:local
container_name: ${COMPOSE_PROJECT_NAME}-web
depends_on:
- api
environment:
NEXT_PUBLIC_API_BASE_URL: http://localhost:8000
NEXT_PUBLIC_APP_BASE_PATH: /fl
NODE_ENV: production
restart: unless-stopped
View File
View File
View File
View File
View File
+46
View File
@@ -0,0 +1,46 @@
server {
listen 3000;
server_name _;
client_max_body_size 200m;
resolver 127.0.0.11 valid=10s;
location /api/v1/ws {
set $backend_api "http://api:8000";
proxy_pass $backend_api;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /api/ {
set $backend_api "http://api:8000";
proxy_pass $backend_api;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location / {
set $backend_web "http://web:3000";
proxy_pass $backend_web;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}