# Meezi — main stack (Postgres, Redis, API, Dashboard, Website, Koja) # # All images/packages served from local Nexus at 171.22.25.73:8081 # Docker images → 171.22.25.73:8081 (docker-group: proxies Docker Hub + MCR) # NuGet → http://171.22.25.73:8081/repository/nuget-group/ # npm → http://171.22.25.73:8081/repository/npm-group/ # # Docker Desktop: add "insecure-registries": ["171.22.25.73:8081"] to daemon.json # # Local dev: # cp .env.example .env # docker compose up -d --build # # Production (IP-based, no domain yet): # Set ENV_FILE secret in Gitea — CI writes .env and runs docker compose up -d # # Production (with domain, add Caddy): # docker compose -f docker-compose.yml -f docker-compose.admin.yml -f docker-compose.caddy.yml up -d # # URLs (port-based defaults): # Dashboard http://SERVER:3101/fa/login # Website http://SERVER:3010/fa # Koja http://SERVER:3103/fa # API http://SERVER:5080/swagger services: postgres: image: ${POSTGRES_IMAGE:-171.22.25.73:8081/repository/docker-group/postgres:16-alpine} container_name: meezi-db restart: unless-stopped environment: POSTGRES_DB: meezi POSTGRES_USER: meezi POSTGRES_PASSWORD: "${DB_PASSWORD:-meezi_local_pass}" ports: - "${POSTGRES_PORT:-5434}:5432" volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U meezi -d meezi"] interval: 5s timeout: 5s retries: 10 redis: image: ${REDIS_IMAGE:-171.22.25.73:8081/repository/docker-group/redis:7-alpine} container_name: meezi-redis restart: unless-stopped ports: - "${REDIS_PORT:-6381}:6379" command: redis-server --appendonly yes volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 10 api: build: context: . dockerfile: docker/api/Dockerfile extra_hosts: - "mirror:host-gateway" args: DOTNET_SDK_IMAGE: ${DOTNET_SDK_IMAGE:-171.22.25.73:8081/repository/docker-group/dotnet/sdk:10.0} DOTNET_ASPNET_IMAGE: ${DOTNET_ASPNET_IMAGE:-171.22.25.73:8081/repository/docker-group/dotnet/aspnet:10.0} container_name: meezi-api restart: unless-stopped depends_on: postgres: condition: service_healthy redis: condition: service_healthy environment: ASPNETCORE_ENVIRONMENT: "${ASPNETCORE_ENVIRONMENT:-Development}" ASPNETCORE_URLS: http://+:8080 RUN_MIGRATIONS: "${RUN_MIGRATIONS:-true}" ConnectionStrings__DefaultConnection: "${DB_CONNECTION_STRING:-Host=postgres;Port=5432;Database=meezi;Username=meezi;Password=meezi_local_pass}" ConnectionStrings__Redis: redis:6379 Jwt__Key: "${JWT_KEY:-dev-jwt-key-CHANGE-THIS-IN-PRODUCTION-min32chars}" App__PublicBaseUrl: "${NEXT_PUBLIC_API_URL:-http://localhost:5080}" App__QrPublicBaseUrl: "${APP_QR_BASE_URL:-http://localhost:3101}" Billing__DashboardBaseUrl: "${BILLING_DASHBOARD_URL:-http://localhost:3101}" Cors__Origins__0: "${CORS_ORIGIN_0:-http://localhost:3101}" Cors__Origins__1: "${CORS_ORIGIN_1:-http://localhost:3010}" Cors__Origins__2: "${CORS_ORIGIN_2:-http://localhost:3103}" Auth__MaxOtpAttemptsPerHour: "${OTP_RATE_LIMIT:-100}" Kavenegar__ApiKey: "${KAVENEGAR_API_KEY:-}" Kavenegar__SenderNumber: "${KAVENEGAR_SENDER:-90005671}" Snappfood__WebhookSecret: "${SNAPPFOOD_WEBHOOK_SECRET:-meezi-dev-snappfood-secret}" ZarinPal__MerchantId: "${ZARINPAL_MERCHANT_ID:-}" ZarinPal__Sandbox: "${ZARINPAL_SANDBOX:-true}" ports: - "${API_PORT:-5080}:8080" volumes: - api_uploads:/app/uploads healthcheck: test: ["CMD-SHELL", "bash -c 'cat /dev/tcp/127.0.0.1/8080' || exit 1"] interval: 10s timeout: 5s retries: 12 start_period: 40s web: build: context: . dockerfile: docker/web/Dockerfile extra_hosts: - "mirror:host-gateway" args: NODE_IMAGE: ${NODE_IMAGE:-171.22.25.73:8081/repository/docker-group/node:20-alpine} NPM_REGISTRY: ${NPM_REGISTRY:-http://171.22.25.73:8081/repository/npm-group/} NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:5080} container_name: meezi-web restart: unless-stopped depends_on: api: condition: service_healthy environment: PORT: "3000" HOSTNAME: 0.0.0.0 ports: - "${WEB_PORT:-3101}:3000" website: build: context: . dockerfile: docker/website/Dockerfile extra_hosts: - "mirror:host-gateway" args: NODE_IMAGE: ${NODE_IMAGE:-171.22.25.73:8081/repository/docker-group/node:20-alpine} NPM_REGISTRY: ${NPM_REGISTRY:-http://171.22.25.73:8081/repository/npm-group/} MEEZI_API_URL: http://api:8080 NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:-http://localhost:3010} container_name: meezi-website restart: unless-stopped depends_on: api: condition: service_healthy environment: PORT: "3000" HOSTNAME: 0.0.0.0 MEEZI_API_URL: http://api:8080 NEXT_PUBLIC_SITE_URL: "${NEXT_PUBLIC_SITE_URL:-http://localhost:3010}" ports: - "${WEBSITE_PORT:-3010}:3000" koja: build: context: . dockerfile: docker/koja/Dockerfile extra_hosts: - "mirror:host-gateway" args: NODE_IMAGE: ${NODE_IMAGE:-171.22.25.73:8081/repository/docker-group/node:20-alpine} NPM_REGISTRY: ${NPM_REGISTRY:-http://171.22.25.73:8081/repository/npm-group/} NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:5080} NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_KOJA_URL:-http://localhost:3103} container_name: meezi-koja restart: unless-stopped depends_on: api: condition: service_healthy environment: PORT: "3000" HOSTNAME: 0.0.0.0 NEXT_PUBLIC_API_URL: "${NEXT_PUBLIC_API_URL:-http://localhost:5080}" NEXT_PUBLIC_SITE_URL: "${NEXT_PUBLIC_KOJA_URL:-http://localhost:3103}" ports: - "${KOJA_PORT:-3103}:3000" volumes: postgres_data: redis_data: api_uploads: