# مقادیر محرمانه از فایل .env ریشه خوانده می‌شوند — از .env.example کپی کنید: # cp .env.example .env # برای انتشار با TLS، روی این فایل docker-compose.prod.yml را هم سوار کنید (README). services: # نقطه ورود واحد — مسیریابی / (سایت استاتیک)، /api (بک‌اند) و /media (MinIO) traefik: image: traefik:v3 restart: unless-stopped command: - --providers.docker=true - --providers.docker.exposedbydefault=false - --entrypoints.web.address=:80 ports: - "${TRAEFIK_HTTP_PORT:-5173}:80" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro db: image: postgres:17-alpine restart: unless-stopped environment: POSTGRES_USER: aramesh POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD را در .env تنظیم کنید} POSTGRES_DB: arameshplaza volumes: - db_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U aramesh -d arameshplaza"] interval: 5s timeout: 5s retries: 12 minio: image: minio/minio:latest restart: unless-stopped command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:-aramesh} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?MINIO_ROOT_PASSWORD را در .env تنظیم کنید} volumes: - minio_data:/data healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 5s timeout: 5s retries: 12 ports: - "9001:9001" # کنسول MinIO — در محیط واقعی با فایروال ببندید labels: - traefik.enable=true - traefik.http.routers.media.rule=PathPrefix(`/media`) - traefik.http.routers.media.entrypoints=web - traefik.http.routers.media.priority=100 - traefik.http.routers.media.middlewares=media-rewrite - traefik.http.middlewares.media-rewrite.replacepathregex.regex=^/media/(.*) - traefik.http.middlewares.media-rewrite.replacepathregex.replacement=/aramesh-media/$$1 - traefik.http.services.media.loadbalancer.server.port=9000 # یک‌بار اجرا می‌شود: ساخت باکت و بازگذاشتن خواندن عمومی برای سرو تصاویر minio-setup: image: minio/mc:latest depends_on: minio: condition: service_healthy environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:-aramesh} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?MINIO_ROOT_PASSWORD را در .env تنظیم کنید} MINIO_BUCKET: aramesh-media restart: "no" entrypoint: > /bin/sh -c " mc alias set local http://minio:9000 $$MINIO_ROOT_USER $$MINIO_ROOT_PASSWORD && mc mb --ignore-existing local/$$MINIO_BUCKET && mc anonymous set download local/$$MINIO_BUCKET && echo 'minio-setup: bucket ready' " backend: build: ./backend restart: unless-stopped environment: DATABASE_URL: postgresql+psycopg://aramesh:${POSTGRES_PASSWORD}@db:5432/arameshplaza SECRET_KEY: ${SECRET_KEY:?SECRET_KEY را در .env تنظیم کنید} CORS_ORIGINS: ${CORS_ORIGINS:-["http://localhost:5173","http://127.0.0.1:5173"]} ADMIN_USERNAME: ${ADMIN_USERNAME:-admin} ADMIN_PASSWORD: ${ADMIN_PASSWORD:?ADMIN_PASSWORD را در .env تنظیم کنید} S3_ENDPOINT: http://minio:9000 S3_ACCESS_KEY: ${MINIO_ROOT_USER:-aramesh} S3_SECRET_KEY: ${MINIO_ROOT_PASSWORD:?MINIO_ROOT_PASSWORD را در .env تنظیم کنید} S3_BUCKET: aramesh-media MEDIA_PUBLIC_BASE: /media # نشانی عمومی سایت — برای sitemap و آدرس مطلق OG (مثل https://aramesh.example) SITE_URL: ${SITE_URL:-} # بیلد فرانت‌اند برای تزریق متای سئو در صفحات /blog و /projects FRONTEND_DIST: /srv/frontend volumes: - ./frontend/dist:/srv/frontend:ro depends_on: db: condition: service_healthy minio: condition: service_healthy healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/api/health')"] interval: 15s timeout: 5s retries: 5 start_period: 20s labels: - traefik.enable=true - traefik.http.routers.api.rule=PathPrefix(`/api`) - traefik.http.routers.api.entrypoints=web - traefik.http.routers.api.priority=100 - traefik.http.services.api.loadbalancer.server.port=8000 # robots.txt و sitemap.xml و صفحات وبلاگ/پروژه با متای سئو — اولویت بالاتر از SPA - traefik.http.routers.seo.rule=PathPrefix(`/blog/`) || Path(`/blog`) || PathPrefix(`/projects/`) || Path(`/projects`) || PathPrefix(`/robots.txt`) || PathPrefix(`/sitemap.xml`) - traefik.http.routers.seo.entrypoints=web - traefik.http.routers.seo.priority=50 - traefik.http.routers.seo.service=api # فقط سرو فایل‌های استاتیک SPA — بیلد روی هاست (npm run build) انجام شده است frontend: build: ./frontend restart: unless-stopped depends_on: - backend - minio healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost/"] interval: 15s timeout: 5s retries: 5 labels: - traefik.enable=true - traefik.http.routers.web.rule=PathPrefix(`/`) - traefik.http.routers.web.entrypoints=web - traefik.http.routers.web.priority=1 - traefik.http.services.web.loadbalancer.server.port=80 # ابزار پشتیبان‌گیری — فقط با پروفایل tools اجرا می‌شود (scripts/backup.sh این کار را می‌کند) mc: image: minio/mc:latest profiles: ["tools"] depends_on: minio: condition: service_healthy environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:-aramesh} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?MINIO_ROOT_PASSWORD را در .env تنظیم کنید} volumes: db_data: minio_data: