Files
meezi/DOCKER.md
T
soroush.asadi 45cd028d1c chore: initial project structure and root configuration
Adds root-level config files: solution (.slnx), NuGet, global.json,
Docker Compose files for all services (API, dashboard, website, finder,
admin), environment example, and developer documentation.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-27 21:33:10 +03:30

5.5 KiB

Meezi — Docker (full platform)

Run all services with one command.

Services

Service Description Default Port
postgres PostgreSQL 16 database 5434 (host)
redis Redis 7 (session, rate-limit, refresh tokens) 6381 (host)
api Main ASP.NET Core 10 API 5080
admin-api Admin ASP.NET Core 10 API 5081
web Customer-facing Next.js dashboard 3101
website Marketing / landing website 3010
admin-web Admin panel Next.js 3102

Quick start — full stack (all 7 services)

cd F:\Projects\Meezi
copy .env.example .env
docker compose -f docker-compose.full.yml up -d --build

Quick start — core stack only (dashboard + API)

docker compose up -d --build

Quick start — with admin panel

docker compose -f docker-compose.yml -f docker-compose.admin.yml up -d --build

Default URLs

Service URL
Dashboard (customer) http://localhost:3101/fa/login
Marketing website http://localhost:3010/fa
Admin panel http://localhost:3102/fa/admin/login
Main API Swagger http://localhost:5080/swagger
Admin API Swagger http://localhost:5081/swagger
Health (main API) http://localhost:5080/health
Health (admin API) http://localhost:5081/health
Hangfire (main API) http://localhost:5080/hangfire

Demo login: 09121234567 — OTP appears in API logs (docker compose logs -f api).


Ports (change in .env)

Variable Default Purpose
WEB_PORT 3101 Next.js dashboard
WEBSITE_PORT 3010 Marketing website
ADMIN_WEB_PORT 3102 Admin panel
API_PORT 5080 Main ASP.NET API
ADMIN_API_PORT 5081 Admin ASP.NET API
POSTGRES_PORT 5434 Postgres on host
REDIS_PORT 6381 Redis on host

If a port is taken, edit .env:

copy .env.example .env
# Edit .env — change WEB_PORT, WEBSITE_PORT, etc.
docker compose -f docker-compose.full.yml up -d --build

Build args and API URLs

NEXT_PUBLIC_API_URL — what the browser uses to call the Main API. Must be a host URL (not api:8080).

MEEZI_API_URL — what the website server uses for internal SSR calls. Uses the Docker service name http://api:8080.

# Rebuild only the website after changing NEXT_PUBLIC_SITE_URL:
docker compose -f docker-compose.full.yml up -d --build website

Useful commands

# Status
docker compose -f docker-compose.full.yml ps

# Logs
docker compose -f docker-compose.full.yml logs -f api
docker compose -f docker-compose.full.yml logs -f website
docker compose -f docker-compose.full.yml logs -f web

# Stop everything
docker compose -f docker-compose.full.yml down

# Stop and remove volumes (wipes DB!)
docker compose -f docker-compose.full.yml down -v

# Rebuild a single service
docker compose -f docker-compose.full.yml up -d --build website
docker compose -f docker-compose.full.yml up -d --build api

Printer setup (inside Docker)

The Meezi API sends print jobs directly from the browser dashboard — the API itself does not talk to printers. This means:

  • Your thermal printer only needs to be on the same WiFi/LAN as the browser running the dashboard
  • No Docker-specific configuration needed for printers
  • See the full guide at: http://localhost:3010/fa/printer-guide

Dev without Docker

Still works:

docker compose up -d postgres redis
# then in separate terminals:
dotnet run --project src/Meezi.API
dotnet run --project src/Meezi.Admin.API
cd web/website && npm run dev   # port 3010
cd web/dashboard && npm run dev # port 3000 → maps to 3101
cd web/admin && npm run dev     # port 3102

Sprint 10 — billing & integrations (dev)

ZarinPal (mock): leave ZarinPal:MerchantId empty. In dashboard تنظیمات → upgrade Pro/Business → redirected through mock pay URL back to /fa/settings?billing=success.

Snappfood webhook (demo café vendor demo_vendor):

$body = '{"orderId":"sf-001","vendorId":"demo_vendor","customerName":"Test","customerPhone":"09121111111","total":150000,"items":[{"name":"لاته","quantity":1,"unitPrice":150000}]}'
$hmac = [System.BitConverter]::ToString((New-Object System.Security.Cryptography.HMACSHA256([Text.Encoding]::UTF8.GetBytes("meezi-dev-snappfood-secret"))).ComputeHash([Text.Encoding]::UTF8.GetBytes($body))).Replace("-","").ToLower()
Invoke-RestMethod -Method Post -Uri "http://localhost:5080/api/webhooks/snappfood" -Body $body -ContentType "application/json" -Headers @{ "X-Snappfood-Signature" = $hmac }

Taraz: Settings → «ارسال به تاراز» (logs only until Taraz:Username is set).

Hangfire: renewal reminder job runs daily — dashboard at http://localhost:5080/hangfire (dev).


Tables & QR

  • Dashboard: /fa/tables — floor plan, add table, print QR (PNG)
  • Dev QR URL in codes: http://localhost:3101/q/{qrCode} (see App__QrPublicBaseUrl)
  • Scan demo_table_01 in Flutter or open manual entry on QR screen

Production env (Arvan)

See DEPLOY.md. Key additional website vars:

NEXT_PUBLIC_SITE_URL=https://meezi.ir
MEEZI_API_URL=http://api:8080

Menu images (Food-101)

  • Manifest: data/menu-image-manifest.json
  • API upserts images on dev seed via EnsureMenuImagesAsync
  • Optional import: dotnet run --project tools/MenuImageImporter -- --food101 <path-to-food-101/images>