diff --git a/.gitignore b/.gitignore index db427d2..cabc252 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,17 @@ deploy/pro-deploy/data/** !deploy/pro-deploy/data/minio/.gitkeep !deploy/pro-deploy/data/postgres/.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 diff --git a/deploy/local/compose.yml b/deploy/local/compose.yml new file mode 100644 index 0000000..1829fad --- /dev/null +++ b/deploy/local/compose.yml @@ -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 diff --git a/deploy/local/data/.gitkeep b/deploy/local/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/deploy/local/data/app/.gitkeep b/deploy/local/data/app/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/deploy/local/data/app/celery/.gitkeep b/deploy/local/data/app/celery/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/deploy/local/data/minio/.gitkeep b/deploy/local/data/minio/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/deploy/local/data/postgres/.gitkeep b/deploy/local/data/postgres/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/deploy/local/data/redis/.gitkeep b/deploy/local/data/redis/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/deploy/local/nginx.conf b/deploy/local/nginx.conf new file mode 100644 index 0000000..8331de3 --- /dev/null +++ b/deploy/local/nginx.conf @@ -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; + } +}