sciagent code + Gitea Actions CI/CD
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,286 @@
|
||||
services:
|
||||
minio:
|
||||
image: quay.io/minio/minio:latest
|
||||
container_name: minio
|
||||
# Host 9000/9001 are often taken; map to free ports on your machine (S3 API / web UI).
|
||||
ports:
|
||||
- "19000:9000" # API / S3 endpoint → http://localhost:19000
|
||||
- "19001:9001" # Web console → http://localhost:19001
|
||||
environment:
|
||||
MINIO_ROOT_USER: minio_user
|
||||
MINIO_ROOT_PASSWORD: minio_password # Use strong password in real projects!
|
||||
# Community MinIO has no per-bucket PutBucketCors (AiStor-only). Browsers need global API CORS for presigned GETs.
|
||||
MINIO_API_CORS_ALLOW_ORIGIN: ${MINIO_API_CORS_ALLOW_ORIGIN:-*}
|
||||
volumes:
|
||||
- ./assets/minio-data:/data
|
||||
command: server /data --console-address ":9001"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
networks:
|
||||
profyt-net:
|
||||
ipv4_address: "10.5.0.3"
|
||||
|
||||
# One-shot: ensure buckets. Browser CORS is MINIO_API_CORS_ALLOW_ORIGIN on the minio service (not mc cors set).
|
||||
minio-cors:
|
||||
image: quay.io/minio/mc:latest
|
||||
container_name: minio-cors
|
||||
depends_on:
|
||||
minio:
|
||||
condition: service_healthy
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- |
|
||||
mc alias set local http://minio:9000 minio_user minio_password
|
||||
for b in initiative-attachments initiative-exports initiative-quarantine imagehub-blobs; do
|
||||
mc mb -p "local/$$b" 2>/dev/null || true
|
||||
done
|
||||
echo "MinIO buckets ensured."
|
||||
networks:
|
||||
profyt-net:
|
||||
ipv4_address: "10.5.0.5"
|
||||
restart: "no"
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: initiative-postgres
|
||||
# Host 5432 is often taken by a local Postgres; map a different port for host access.
|
||||
ports:
|
||||
- "15432:5432"
|
||||
environment:
|
||||
POSTGRES_USER: initiative
|
||||
POSTGRES_PASSWORD: initiative_secret
|
||||
POSTGRES_DB: initiatives
|
||||
volumes:
|
||||
- initiative_pg_data:/var/lib/postgresql/data
|
||||
# Schema lives under be0 (dyd/0backend/migrations is not in this repo).
|
||||
- ./be0/migrations/001_initiative_schema.sql:/docker-entrypoint-initdb.d/01_initiative_schema.sql:ro
|
||||
- ./be0/migrations/002_application_storage_extensions.sql:/docker-entrypoint-initdb.d/02_application_storage_extensions.sql:ro
|
||||
- ./be0/migrations/003_review_documents.sql:/docker-entrypoint-initdb.d/03_review_documents.sql:ro
|
||||
- ./be0/migrations/004_evidence_artifact_review.sql:/docker-entrypoint-initdb.d/04_evidence_artifact_review.sql:ro
|
||||
- ./be0/migrations/004_application_admin_results.sql:/docker-entrypoint-initdb.d/05_application_admin_results.sql:ro
|
||||
- ./be0/migrations/006_user_notifications.sql:/docker-entrypoint-initdb.d/06_user_notifications.sql:ro
|
||||
- ./be0/migrations/007_user_roles_email_policy_admin.sql:/docker-entrypoint-initdb.d/07_user_roles_email_policy_admin.sql:ro
|
||||
- ./be0/migrations/008_audit_events.sql:/docker-entrypoint-initdb.d/08_audit_events.sql:ro
|
||||
- ./be0/migrations/009_backup_artifact_roles_storage_kind.sql:/docker-entrypoint-initdb.d/09_backup_artifact_roles_storage_kind.sql:ro
|
||||
- ./be0/migrations/010_user_staff_profiles.sql:/docker-entrypoint-initdb.d/10_user_staff_profiles.sql:ro
|
||||
- ./be0/migrations/011_academic_titles_vn.sql:/docker-entrypoint-initdb.d/11_academic_titles_vn.sql:ro
|
||||
- ./be0/migrations/012_password_reset.sql:/docker-entrypoint-initdb.d/12_password_reset.sql:ro
|
||||
- ./be0/migrations/013_email_verification.sql:/docker-entrypoint-initdb.d/13_email_verification.sql:ro
|
||||
- ./be0/migrations/014_registration_otp.sql:/docker-entrypoint-initdb.d/14_registration_otp.sql:ro
|
||||
- ./be0/migrations/015_document_templates.sql:/docker-entrypoint-initdb.d/15_document_templates.sql:ro
|
||||
- ./be0/migrations/016_research_projects.sql:/docker-entrypoint-initdb.d/16_research_projects.sql:ro
|
||||
- ./be0/migrations/017_imagehub_datasets.sql:/docker-entrypoint-initdb.d/17_imagehub_datasets.sql:ro
|
||||
- ./be0/migrations/018_imagehub_segmentation_links.sql:/docker-entrypoint-initdb.d/18_imagehub_segmentation_links.sql:ro
|
||||
- ./be0/migrations/019_imagehub_cloud_import.sql:/docker-entrypoint-initdb.d/19_imagehub_cloud_import.sql:ro
|
||||
- ./be0/migrations/020_imagehub_dataset_stages.sql:/docker-entrypoint-initdb.d/20_imagehub_dataset_stages.sql:ro
|
||||
- ./be0/migrations/021_imagehub_task_pipeline.sql:/docker-entrypoint-initdb.d/21_imagehub_task_pipeline.sql:ro
|
||||
- ./be0/migrations/022_imagehub_task_annotations.sql:/docker-entrypoint-initdb.d/22_imagehub_task_annotations.sql:ro
|
||||
- ./be0/migrations/023_imagehub_dataset_members.sql:/docker-entrypoint-initdb.d/23_imagehub_dataset_members.sql:ro
|
||||
- ./be0/migrations/024_imagehub_dataset_project_link.sql:/docker-entrypoint-initdb.d/24_imagehub_dataset_project_link.sql:ro
|
||||
- ./be0/migrations/025_imagehub_task_review_events.sql:/docker-entrypoint-initdb.d/25_imagehub_task_review_events.sql:ro
|
||||
- ./be0/migrations/026_imagehub_file_folder_path.sql:/docker-entrypoint-initdb.d/26_imagehub_file_folder_path.sql:ro
|
||||
- ./be0/migrations/027_imagehub_dataset_label_map.sql:/docker-entrypoint-initdb.d/27_imagehub_dataset_label_map.sql:ro
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U initiative -d initiatives"]
|
||||
interval: 3s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
start_period: 10s
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
profyt-net:
|
||||
ipv4_address: "10.5.0.10"
|
||||
|
||||
# ── Frontends ───────────────────────────────────────────────────────────────
|
||||
# Two SPAs built from the npm workspace (shared kernel + each app). The browser
|
||||
# calls same-origin /api/*; Vite proxies to be0 (localhost:4402 is wrong inside the
|
||||
# container). Build context is the repo ROOT — the workspace — not the app dir, so
|
||||
# `@ump/shared` (../shared/src) resolves. Dev mode: bind-mount the workspace + reinstall
|
||||
# on start so new deps land in the isolated node_modules volume.
|
||||
frontend_user:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: frontend_user/Dockerfile
|
||||
container_name: frontend_user
|
||||
ipc: host
|
||||
ports:
|
||||
- 8081:5173
|
||||
environment:
|
||||
- GENERIC_TIMEZONE=UTC
|
||||
- VITE_DEV_PROXY_TARGET=http://be0:4402
|
||||
# When unset, Vite allows all hosts. Set e.g. YOUR_IP,localhost for cloud/LAN dev.
|
||||
- VITE_ALLOWED_HOSTS=${VITE_ALLOWED_HOSTS:-}
|
||||
volumes:
|
||||
- ./package.json:/app/package.json
|
||||
- ./package-lock.json:/app/package-lock.json
|
||||
- ./shared:/app/shared
|
||||
- ./frontend_user:/app/frontend_user
|
||||
- ./frontend_admin:/app/frontend_admin
|
||||
- ./frontend_investigator:/app/frontend_investigator
|
||||
- ./frontend_publisher:/app/frontend_publisher
|
||||
# Isolated workspace-hoisted node_modules (not shadowed by the host).
|
||||
- /app/node_modules
|
||||
command: ["sh", "-c", "npm install && npm run dev -w frontend_user -- --host 0.0.0.0 --port 5173"]
|
||||
depends_on:
|
||||
be0:
|
||||
condition: service_started
|
||||
networks:
|
||||
profyt-net:
|
||||
ipv4_address: "10.5.0.4"
|
||||
|
||||
frontend_admin:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: frontend_admin/Dockerfile
|
||||
container_name: frontend_admin
|
||||
ipc: host
|
||||
ports:
|
||||
- 8082:5174
|
||||
environment:
|
||||
- GENERIC_TIMEZONE=UTC
|
||||
- VITE_DEV_PROXY_TARGET=http://be0:4402
|
||||
- VITE_ALLOWED_HOSTS=${VITE_ALLOWED_HOSTS:-}
|
||||
volumes:
|
||||
- ./package.json:/app/package.json
|
||||
- ./package-lock.json:/app/package-lock.json
|
||||
- ./shared:/app/shared
|
||||
- ./frontend_user:/app/frontend_user
|
||||
- ./frontend_admin:/app/frontend_admin
|
||||
- ./frontend_investigator:/app/frontend_investigator
|
||||
- ./frontend_publisher:/app/frontend_publisher
|
||||
- /app/node_modules
|
||||
command: ["sh", "-c", "npm install && npm run dev -w frontend_admin -- --host 0.0.0.0 --port 5174"]
|
||||
depends_on:
|
||||
be0:
|
||||
condition: service_started
|
||||
networks:
|
||||
profyt-net:
|
||||
ipv4_address: "10.5.0.6"
|
||||
|
||||
frontend_investigator:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: frontend_investigator/Dockerfile
|
||||
container_name: frontend_investigator
|
||||
ipc: host
|
||||
ports:
|
||||
- 8083:5175
|
||||
environment:
|
||||
- GENERIC_TIMEZONE=UTC
|
||||
- VITE_DEV_PROXY_TARGET=http://be0:4402
|
||||
- VITE_ALLOWED_HOSTS=${VITE_ALLOWED_HOSTS:-}
|
||||
volumes:
|
||||
- ./package.json:/app/package.json
|
||||
- ./package-lock.json:/app/package-lock.json
|
||||
- ./shared:/app/shared
|
||||
- ./frontend_user:/app/frontend_user
|
||||
- ./frontend_admin:/app/frontend_admin
|
||||
- ./frontend_investigator:/app/frontend_investigator
|
||||
- ./frontend_publisher:/app/frontend_publisher
|
||||
- /app/node_modules
|
||||
command: ["sh", "-c", "npm install && npm run dev -w frontend_investigator -- --host 0.0.0.0 --port 5175"]
|
||||
depends_on:
|
||||
be0:
|
||||
condition: service_started
|
||||
networks:
|
||||
profyt-net:
|
||||
ipv4_address: "10.5.0.7"
|
||||
|
||||
frontend_publisher:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: frontend_publisher/Dockerfile
|
||||
container_name: frontend_publisher
|
||||
ipc: host
|
||||
ports:
|
||||
- 8084:5176
|
||||
environment:
|
||||
- GENERIC_TIMEZONE=UTC
|
||||
- VITE_DEV_PROXY_TARGET=http://be0:4402
|
||||
- VITE_ALLOWED_HOSTS=${VITE_ALLOWED_HOSTS:-}
|
||||
volumes:
|
||||
- ./package.json:/app/package.json
|
||||
- ./package-lock.json:/app/package-lock.json
|
||||
- ./shared:/app/shared
|
||||
- ./frontend_user:/app/frontend_user
|
||||
- ./frontend_admin:/app/frontend_admin
|
||||
- ./frontend_investigator:/app/frontend_investigator
|
||||
- ./frontend_publisher:/app/frontend_publisher
|
||||
- /app/node_modules
|
||||
command: ["sh", "-c", "npm install && npm run dev -w frontend_publisher -- --host 0.0.0.0 --port 5176"]
|
||||
depends_on:
|
||||
be0:
|
||||
condition: service_started
|
||||
networks:
|
||||
profyt-net:
|
||||
ipv4_address: "10.5.0.8"
|
||||
|
||||
be0:
|
||||
build:
|
||||
context: ./be0
|
||||
dockerfile: Dockerfile
|
||||
container_name: be0
|
||||
ipc: host
|
||||
ports:
|
||||
- 4402:4402
|
||||
environment:
|
||||
# Dev stack: hot-reload API when bind-mounting ./be0
|
||||
- UVICORN_RELOAD=1
|
||||
- GENERIC_TIMEZONE=UTC
|
||||
- INITIATIVE_DATABASE_URL=postgresql+asyncpg://initiative:initiative_secret@postgres:5432/initiatives
|
||||
- APPLICATION_DRAFT_DIR=/app/assets/application-drafts
|
||||
# Shared with fe0 `public/submitted-initiatives` so PDFs written by be0 are served by Vite static.
|
||||
- SUBMITTED_INITIATIVES_DIR=/app/submitted-initiatives
|
||||
# From inside the be0 container, reach MinIO on the shared Docker network (not localhost:19000).
|
||||
- S3_ENDPOINT_URL=http://minio:9000
|
||||
- S3_ACCESS_KEY=minio_user
|
||||
- S3_SECRET_KEY=minio_password
|
||||
- S3_BUCKET_ATTACHMENTS=initiative-attachments
|
||||
- S3_BUCKET_EXPORTS=initiative-exports
|
||||
- S3_BUCKET_QUARANTINE=initiative-quarantine
|
||||
# Presigned « Xem / tải » links in the browser must hit the host-mapped MinIO port, not minio:9000.
|
||||
- S3_PUBLIC_ENDPOINT_URL=${S3_PUBLIC_ENDPOINT_URL:-http://localhost:19000}
|
||||
# Optional: comma-separated; merged with localhost defaults (e.g. http://YOUR_IP:8081 for LAN deploys).
|
||||
- CORS_ORIGINS=${CORS_ORIGINS:-}
|
||||
# Optional: comma-separated institutional admin emails. When unset, auth_api uses built-in UMP allow-list.
|
||||
- AUTH_ADMIN_EMAILS=${AUTH_ADMIN_EMAILS:-}
|
||||
# SMTP (Option A) — OTP + password-reset email. Set SMTP_HOST (and secrets) in repo-root .env; see .env.example.
|
||||
- SMTP_HOST=${SMTP_HOST:-}
|
||||
- SMTP_PORT=${SMTP_PORT:-587}
|
||||
- SMTP_USER=${SMTP_USER:-}
|
||||
- SMTP_PASSWORD=${SMTP_PASSWORD:-}
|
||||
- AUTH_MAIL_FROM=${AUTH_MAIL_FROM:-}
|
||||
- SMTP_USE_TLS=${SMTP_USE_TLS:-1}
|
||||
- AUTH_PUBLIC_WEB_ORIGIN=${AUTH_PUBLIC_WEB_ORIGIN:-http://localhost:8081}
|
||||
# Dev-only: OTP/link in stdout instead of SMTP — leave unset when using SMTP above.
|
||||
- AUTH_MAIL_LOG_ONLY=${AUTH_MAIL_LOG_ONLY:-}
|
||||
# DOCX mẫu hồ sơ (Xem lại) — cùng file với fe0/public/…/template_application_form.docx
|
||||
- TEMPLATE_APPLICATION_FORM_DOCX=/app/template_application_form.docx
|
||||
volumes:
|
||||
- ./be0:/app
|
||||
- ./assets:/app/assets
|
||||
- ./assets/submitted-initiatives:/app/submitted-initiatives
|
||||
- ./fe0/public/assets/template_application_form.docx:/app/template_application_form.docx:ro
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
minio:
|
||||
condition: service_healthy
|
||||
# One-shot minio-cors must finish first so buckets exist (Compose v2.13+).
|
||||
minio-cors:
|
||||
condition: service_completed_successfully
|
||||
networks:
|
||||
profyt-net:
|
||||
ipv4_address: "10.5.0.2"
|
||||
|
||||
volumes:
|
||||
initiative_pg_data:
|
||||
|
||||
networks:
|
||||
profyt-net:
|
||||
driver: bridge
|
||||
ipam:
|
||||
config:
|
||||
- subnet: "10.5.0.0/16"
|
||||
Reference in New Issue
Block a user