docker-compose.yml
Rama main · réplica de lectura del repositorio original.
# Phonix — full stack (ASP.NET Core API + Next.js storefront) on a single host.
# Config comes from a sibling .env file (copy .env.example → .env and edit before first run).
# docker compose up -d --build
services:
backend:
build:
context: ./backend
dockerfile: Dockerfile
image: phonix-backend
container_name: phonix-backend
restart: unless-stopped
environment:
ASPNETCORE_ENVIRONMENT: Production
ASPNETCORE_URLS: http://+:5228
# Public URL of the storefront — used for CORS, email links, and the verify/reset URLs.
PHONIX_FRONTEND_URL: ${PHONIX_FRONTEND_URL:-http://localhost:3000}
# ALL durable state lands under the mounted volume so it survives rebuilds/redeploys: the store,
# the audit log, uploaded media (profile/product/site images + KYC docs), the session key ring,
# and logs. Set explicitly so persistence never relies on the app's (per-release) base directory.
PHONIX_DATA_FILE: /app/App_Data/store.json
PHONIX_AUDIT_FILE: /app/App_Data/audit_store.json
PHONIX_UPLOADS_DIR: /app/App_Data/ProtectedUploads
PHONIX_KEYS_DIR: /app/App_Data/keys
PHONIX_LOG_DIR: /app/App_Data/logs
# Set both to "true" only when a TLS-terminating reverse proxy sits in front (see DEPLOY.md).
PHONIX_BEHIND_PROXY: ${PHONIX_BEHIND_PROXY:-false}
PHONIX_TRUSTED_PROXIES: ${PHONIX_TRUSTED_PROXIES:-127.0.0.1}
PHONIX_FORCE_HTTPS: ${PHONIX_FORCE_HTTPS:-false}
# (Re)applied on every boot: mints the first admin account if it doesn't exist yet, or fixes its
# role/password if it does. Without these, a fresh deploy has NO way to reach the admin panel.
PHONIX_OWNER_USERNAME: ${PHONIX_OWNER_USERNAME:-}
PHONIX_OWNER_PASSWORD: ${PHONIX_OWNER_PASSWORD:-}
# Encrypts store backups downloaded/sent from /admin/backup (AES-256-GCM). Optional — without it,
# backup files are plain JSON/zip. Losing this key after the fact makes old encrypted backups
# unrecoverable, so set it once and keep it somewhere safe outside the server.
PHONIX_BACKUP_KEY: ${PHONIX_BACKUP_KEY:-}
# Optional High Availability (one Primary + one Standby, business continuity only). Leave
# PHONIX_CLUSTER_MODE unset/standalone for a normal single-server install — every var below is a
# no-op in that case. scripts/install.sh prompts for these when clustering is chosen.
PHONIX_CLUSTER_MODE: ${PHONIX_CLUSTER_MODE:-standalone}
PHONIX_NODE_ID: ${PHONIX_NODE_ID:-}
PHONIX_CLUSTER_PEER: ${PHONIX_CLUSTER_PEER:-}
PHONIX_CLUSTER_SECRET: ${PHONIX_CLUSTER_SECRET:-}
# PHONIX_CLUSTER_PEER MUST be an https:// URL — cluster sync carries orders/user data and the initial
# snapshot, so the link is required to be encrypted. Set this to "true" ONLY for local/dev testing over
# plain HTTP; the server refuses to start with an http:// peer otherwise.
PHONIX_CLUSTER_ALLOW_INSECURE: ${PHONIX_CLUSTER_ALLOW_INSECURE:-}
# How often a Standby reconciles uploaded media (KYC/avatars/product images) with the Primary. Default 60s.
PHONIX_CLUSTER_MEDIA_SYNC_INTERVAL_SECONDS: ${PHONIX_CLUSTER_MEDIA_SYNC_INTERVAL_SECONDS:-}
volumes:
- phonix-data:/app/App_Data
ports:
- "${BACKEND_PORT:-5228}:5228"
# Lets the container reach the host's Postfix (port 25) via host.docker.internal.
extra_hosts:
- "host.docker.internal:host-gateway"
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:5228/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
args:
# Baked into the client bundle at build time — must be the PUBLIC API URL the browser reaches.
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:5228}
image: phonix-frontend
container_name: phonix-frontend
restart: unless-stopped
depends_on:
backend:
condition: service_healthy
ports:
- "${FRONTEND_PORT:-3000}:3000"
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000',r=>process.exit(r.statusCode<500?0:1)).on('error',()=>process.exit(1))"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
volumes:
phonix-data: