feat: Add environment configuration files and update Docker Compose setup for development and production

This commit is contained in:
MaddoScientisto 2026-04-20 19:58:42 +02:00
commit 539a848e95
8 changed files with 292 additions and 193 deletions

35
faceai/.env.development Normal file
View file

@ -0,0 +1,35 @@
NODE_ENV=development
FACEAI_CLIENT_DEV_IMAGE=node:20-alpine
FACEAI_PROCESSOR_DEV_IMAGE=regalami-faceai-processor-local
FACEAI_PORT=3001
FACEAI_PUBLISHED_PORT=3001
FACEAI_LEGACY_PHP_PORT=8080
FACEAI_FRONTEND_URL=http://localhost:3001
FACEAI_PUBLIC_BASE_URL=http://localhost:3001
FACEAI_LEGACY_RETURN_URL=http://localhost:8080/faceai_return.php
FACEAI_LEGACY_HOME_URL=http://localhost:8080/index.jsp
FACEAI_ENABLE_LOCAL_LEGACY_STATIC=1
FACEAI_LOCAL_LEGACY_STATIC_ROOT=/legacy-www
FACEAI_SHARED_SECRET=disagio-spaghetti-science-lol-boh
FACEAI_SESSION_COOKIE=rus_faceai_session
FACEAI_REDIS_URL=redis://redis:6379
FACEAI_QUEUE_NAME=faceai-searches
FACEAI_RUNTIME_ROOT=/data/runtime
FACEAI_UPLOAD_ROOT=/data/runtime/uploads
FACEAI_LOG_ROOT=/data/logs
FACEAI_PKL_ROOT=/data/pkl
FACEAI_MATCHER_BINARY=/app/bin/face_matcher
FACEAI_WORKER_CONCURRENCY=2
FACEAI_WORKER_TIMEOUT_MS=300000
FACEAI_PROCESSOR_HEARTBEAT_GRACE_MS=20000
FACEAI_PROCESSOR_HEARTBEAT_INTERVAL_MS=5000
FACEAI_PROCESSOR_HEARTBEAT_TTL_SECONDS=20
FACEAI_FEATURE_ENABLED=1
FACEAI_BACKEND_INTERNAL_URL=http://faceai:3001
FACEAI_ALLOW_DEV_HANDOFF=1
FACEAI_IDENTITY_COOKIE=rus_faceai_identity
LIVE_SITE_BASE_URL=https://www.regalamiunsorriso.it
LIVE_SITE_LOGIN_URL=https://www.regalamiunsorriso.it/login_clienti-it.html
LIVE_SITE_RACE_URL=https://www.regalamiunsorriso.it/42%20HALF%20MARATHON%20FIRENZE_gara-1018545---96-1.html
LIVE_SITE_USERNAME=piero
LIVE_SITE_PASSWORD=AA25061958Pg!

View file

@ -1,22 +1,46 @@
PORT=3001
FACEAI_FRONTEND_URL=http://localhost:5173
FACEAI_PUBLIC_BASE_URL=http://localhost:3001
FACEAI_LEGACY_RETURN_URL=http://localhost:3001/dev/legacy/return
FACEAI_LEGACY_HOME_URL=http://localhost:8080/index.jsp
FACEAI_ENABLE_LOCAL_LEGACY_STATIC=1
FACEAI_LOCAL_LEGACY_STATIC_ROOT=k:\various\regalamiunsorriso\www
# Compose usage:
# docker compose -f docker-compose.yml --env-file .env.production up -d
# docker compose --env-file .env.development up --build
NODE_ENV=production
FACEAI_CLIENT_IMAGE=forgejo.maddoscientisto.net/maddo/faceai-client:latest
FACEAI_PROCESSOR_IMAGE=forgejo.maddoscientisto.net/maddo/faceai-processor:latest
FACEAI_REDIS_IMAGE=redis:7-alpine
FACEAI_CLIENT_CONTAINER_NAME=regalami-faceai
FACEAI_PROCESSOR_CONTAINER_NAME=regalami-faceai-processor
FACEAI_REDIS_CONTAINER_NAME=regalami-faceai-redis
FACEAI_CLIENT_DEV_IMAGE=node:20-alpine
FACEAI_PROCESSOR_DEV_IMAGE=regalami-faceai-processor-local
FACEAI_PORT=3001
FACEAI_PUBLISHED_PORT=3001
FACEAI_LEGACY_PHP_PORT=8080
FACEAI_FRONTEND_URL=https://ai.regalamiunsorriso.it
FACEAI_PUBLIC_BASE_URL=https://ai.regalamiunsorriso.it
FACEAI_LEGACY_RETURN_URL=https://www.regalamiunsorriso.it/faceai_return.php
FACEAI_LEGACY_HOME_URL=https://www.regalamiunsorriso.it
FACEAI_ENABLE_LOCAL_LEGACY_STATIC=0
FACEAI_LOCAL_LEGACY_STATIC_ROOT=/legacy-www
FACEAI_SHARED_SECRET=change-me
FACEAI_SESSION_COOKIE=rus_faceai_session
FACEAI_IDENTITY_COOKIE=rus_faceai_identity
FACEAI_REDIS_URL=redis://redis:6379
FACEAI_QUEUE_NAME=faceai-searches
FACEAI_RUNTIME_ROOT=/data/runtime
FACEAI_UPLOAD_ROOT=/data/runtime/uploads
FACEAI_LOG_ROOT=/data/logs
FACEAI_PKL_ROOT=/data/pkl
FACEAI_RUNTIME_BIND=/mnt/storage/data/faceai/runtime
FACEAI_LOG_BIND=/mnt/storage/data/faceai/logs
FACEAI_PKL_BIND=/mnt/nas12/nas2/RUS
FACEAI_MATCHER_BINARY=/app/bin/face_matcher
FACEAI_WORKER_CONCURRENCY=8
FACEAI_WORKER_TIMEOUT_MS=300000
FACEAI_PROCESSOR_HEARTBEAT_GRACE_MS=20000
FACEAI_PROCESSOR_HEARTBEAT_INTERVAL_MS=5000
FACEAI_PROCESSOR_HEARTBEAT_TTL_SECONDS=20
FACEAI_FEATURE_ENABLED=1
FACEAI_BACKEND_INTERNAL_URL=http://faceai:3001
FACEAI_ALLOW_DEV_HANDOFF=1
LIVE_SITE_BASE_URL=https://www.regalamiunsorriso.it
LIVE_SITE_LOGIN_URL=https://www.regalamiunsorriso.it/login_clienti-it.html
LIVE_SITE_RACE_URL=https://www.regalamiunsorriso.it/42%20HALF%20MARATHON%20FIRENZE_gara-1018545---96-1.html

28
faceai/.env.production Normal file
View file

@ -0,0 +1,28 @@
NODE_ENV=production
FACEAI_CLIENT_IMAGE=forgejo.maddoscientisto.net/maddo/faceai-client:latest
FACEAI_PROCESSOR_IMAGE=forgejo.maddoscientisto.net/maddo/faceai-processor:latest
FACEAI_REDIS_IMAGE=redis:7-alpine
FACEAI_CLIENT_CONTAINER_NAME=regalami-faceai
FACEAI_PROCESSOR_CONTAINER_NAME=regalami-faceai-processor
FACEAI_REDIS_CONTAINER_NAME=regalami-faceai-redis
FACEAI_PORT=3001
FACEAI_PUBLISHED_PORT=3001
FACEAI_FRONTEND_URL=https://ai.regalamiunsorriso.it
FACEAI_PUBLIC_BASE_URL=https://ai.regalamiunsorriso.it
FACEAI_LEGACY_RETURN_URL=https://www.regalamiunsorriso.it/faceai_return.php
FACEAI_LEGACY_HOME_URL=https://www.regalamiunsorriso.it
FACEAI_SHARED_SECRET=disagio-spaghetti-science-lol-boh
FACEAI_SESSION_COOKIE=rus_faceai_session
FACEAI_REDIS_URL=redis://redis:6379
FACEAI_QUEUE_NAME=faceai-searches
FACEAI_RUNTIME_ROOT=/data/runtime
FACEAI_UPLOAD_ROOT=/data/runtime/uploads
FACEAI_LOG_ROOT=/data/logs
FACEAI_PKL_ROOT=/data/pkl
FACEAI_RUNTIME_BIND=/mnt/storage/data/faceai/runtime
FACEAI_LOG_BIND=/mnt/storage/data/faceai/logs
FACEAI_PKL_BIND=/mnt/nas12/nas2/RUS
FACEAI_MATCHER_BINARY=/app/bin/face_matcher
FACEAI_WORKER_CONCURRENCY=8
FACEAI_WORKER_TIMEOUT_MS=300000
FACEAI_ENABLE_LOCAL_LEGACY_STATIC=0

View file

@ -63,10 +63,17 @@ From this folder:
```bash
npm install
npm run build
docker compose up --build
docker compose --env-file .env.development up --build
```
The checked-in `docker-compose.yml` starts:
The checked-in Compose setup now uses:
- `docker-compose.yml` as the production-ready base stack
- `docker-compose.override.yml` as the local development overlay
- `.env.production` for production-oriented values
- `.env.development` for the local simulator workflow
The local development stack started by the command above combines the base file and the override and starts:
- FaceAI public site on `http://localhost:3001`
- processor runner on the internal Compose network
@ -85,7 +92,7 @@ The `processor` service is built from `docker/processor.Dockerfile` using the re
The checked-in local Compose stack now mirrors the relevant Node service logs to both Docker stdout/stderr and `faceai/logs` on the host.
After `docker compose up --build`, inspect:
After `docker compose --env-file .env.development up --build`, inspect:
- `faceai/logs/backend.log` for backend startup and API-side failures
- `faceai/logs/processor.log` for worker startup, queue processing, and uncaught processor errors
@ -131,7 +138,7 @@ npm run build
If you want to stop and remove the local containers afterward, run:
```bash
docker compose down
docker compose --env-file .env.development down
```
### Automated End-To-End Test
@ -149,7 +156,7 @@ npm run test:e2e
The suite will:
- build the frontend bundle
- start `docker compose up --build -d`
- start `docker compose --env-file .env.development up --build -d`
- open `http://localhost:8080/faceai_simulator.php?raceId=202&lang=it`
- click the `Face ID` launch button injected by `www/_js/rus-ecom-240621.js`
- upload `test_pkl/test_images/DSC_1960.JPG`
@ -237,7 +244,7 @@ One workable loop is:
```bash
npm install
docker compose up redis -d
docker compose --env-file .env.development up redis -d
npm run dev
```
@ -245,7 +252,9 @@ Then start the processor in a second shell, either with its own local environmen
## Docker Compose Deployment For The Public Site And Matcher Runner
The checked-in `docker-compose.yml` is for local integration testing because it also includes the PHP simulator and local bind mounts. For hosted deployment, keep the same three-service application topology but remove `legacy-php` and replace the local mounts with the real production paths on the host.
The checked-in `docker-compose.yml` is now the production-ready base stack for hosted deployment. The checked-in `docker-compose.override.yml` is the development overlay that restores the local PHP simulator, workspace bind mounts, and development-oriented commands.
Because Docker Compose auto-loads `docker-compose.override.yml` when it is present in the same directory, production-style runs from this workspace must explicitly select only the base file.
The public FaceAI site and the matcher runner can both use the same application image. The difference is only the process command:
@ -254,102 +263,25 @@ The public FaceAI site and the matcher runner can both use the same application
If that shared image also embeds or mounts the current Linux `face_matcher` build, make sure the base OS provides `GLIBC_2.38` or newer and includes `libxcb1`. A Debian Trixie-based image with that package installed satisfies the requirement; a Bookworm-based image does not.
### Production Compose Example
### Production Compose Commands
This example assumes:
This setup assumes:
- FaceAI runtime files, logs, and matcher binaries live under `/var/docker/faceai` on the host
- the NAS export is already mounted on the host at `/mnt/nas12` via `/etc/fstab`, for example `192.168.10.247:/public /mnt/nas12 nfs rw,noatime 0 0`
- the race dataset root is available on the host at `/mnt/nas12/nas2/RUS`
Replace the registry path and secrets with the real deployment values.
Set the real production values in `.env.production`, then run:
```yaml
services:
faceai:
image: forgejo.maddoscientisto.net/maddo/faceai-client:latest
container_name: regalami-faceai
restart: unless-stopped
command:
- node
- docker/run-with-log-file.mjs
- /data/logs/backend.log
- npm
- run
- start
environment:
NODE_ENV: production
PORT: 3001
FACEAI_FRONTEND_URL: https://ai.regalamiunsorriso.it
FACEAI_PUBLIC_BASE_URL: https://ai.regalamiunsorriso.it
FACEAI_LEGACY_RETURN_URL: https://www.regalamiunsorriso.it/faceai_return.php
FACEAI_SHARED_SECRET: disagio-spaghetti-science-lol-boh
FACEAI_SESSION_COOKIE: rus_faceai_session
FACEAI_REDIS_URL: redis://redis:6379
FACEAI_QUEUE_NAME: faceai-searches
FACEAI_RUNTIME_ROOT: /data/runtime
FACEAI_UPLOAD_ROOT: /data/runtime/uploads
FACEAI_LOG_ROOT: /data/logs
FACEAI_PKL_ROOT: /data/pkl
FACEAI_PROCESSOR_HEARTBEAT_GRACE_MS: 20000
FACEAI_ENABLE_LOCAL_LEGACY_STATIC: 0
volumes:
- /mnt/storage/data/faceai/runtime:/data/runtime
- /mnt/storage/data/faceai/logs:/data/logs
- /mnt/nas12/nas2/RUS:/data/pkl:ro
ports:
- "3001:3001"
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3001/health').then(async (response) => { const payload = await response.json().catch(() => ({})); if (!response.ok || payload.ok !== true) { console.error(JSON.stringify(payload)); process.exit(1); } }).catch((error) => { console.error(error.stack || error.message); process.exit(1); })"]
interval: 10s
timeout: 5s
retries: 6
start_period: 20s
depends_on:
redis:
condition: service_healthy
```bash
docker compose -f docker-compose.yml --env-file .env.production up -d
```
processor:
image: forgejo.maddoscientisto.net/maddo/faceai-processor:latest
container_name: regalami-faceai-processor
restart: unless-stopped
command:
- node
- docker/run-with-log-file.mjs
- /data/logs/processor.log
- npm
- run
- start:processor
environment:
NODE_ENV: production
FACEAI_REDIS_URL: redis://redis:6379
FACEAI_QUEUE_NAME: faceai-searches
FACEAI_RUNTIME_ROOT: /data/runtime
FACEAI_LOG_ROOT: /data/logs
FACEAI_PKL_ROOT: /data/pkl
FACEAI_MATCHER_BINARY: /app/bin/face_matcher
FACEAI_PROCESSOR_HEARTBEAT_INTERVAL_MS: 5000
FACEAI_PROCESSOR_HEARTBEAT_TTL_SECONDS: 20
FACEAI_WORKER_CONCURRENCY: 2
FACEAI_WORKER_TIMEOUT_MS: 300000
volumes:
- /mnt/storage/data/faceai/runtime:/data/runtime
- /mnt/storage/data/faceai/logs:/data/logs
- /mnt/nas12/nas2/RUS:/data/pkl:ro
depends_on:
redis:
condition: service_healthy
To pull newer images before a rollout:
redis:
image: redis:7-alpine
container_name: regalami-faceai-redis
restart: unless-stopped
command: redis-server --appendonly no
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 12
```bash
docker compose -f docker-compose.yml --env-file .env.production pull
docker compose -f docker-compose.yml --env-file .env.production up -d
```
This pattern assumes a reverse proxy on the host publishes `https://ai.regalamiunsorriso.it` and forwards to `127.0.0.1:3001`. The processor is internal-only and does not expose any public port.
@ -451,16 +383,37 @@ This scaffold can now be deployed with the public site, processor, and Redis, bu
So the Compose deployment is appropriate for hosted integration and controlled production-like rollout, but not yet for the final hardened architecture described in the integration plan.
## Environment
## Environment Files
Defaults are already set for local development, but these can be overridden:
The repository now keeps separate env files for the two compose workflows:
- `.env.production`: production-oriented values used with the base compose file only
- `.env.development`: local simulator values used with the base file plus the override
To start the local development stack:
```bash
docker compose --env-file .env.development up --build
```
To start the production-style stack from this workspace without loading the development override:
```bash
docker compose -f docker-compose.yml --env-file .env.production up -d
```
If you need a template that lists all supported variables, use `.env.example`.
The most important development defaults are:
```text
PORT=3001
FACEAI_FRONTEND_URL=http://localhost:5173
NODE_ENV=development
FACEAI_PORT=3001
FACEAI_FRONTEND_URL=http://localhost:3001
FACEAI_PUBLIC_BASE_URL=http://localhost:3001
FACEAI_LEGACY_RETURN_URL=http://localhost:3001/dev/legacy/return
FACEAI_LEGACY_RETURN_URL=http://localhost:8080/faceai_return.php
FACEAI_LEGACY_HOME_URL=http://localhost:8080/index.jsp
FACEAI_FEATURE_ENABLED=1
FACEAI_SHARED_SECRET=change-me
FACEAI_SESSION_COOKIE=rus_faceai_session
FACEAI_REDIS_URL=redis://redis:6379
@ -469,19 +422,19 @@ FACEAI_RUNTIME_ROOT=/data/runtime
FACEAI_UPLOAD_ROOT=/data/runtime/uploads
FACEAI_LOG_ROOT=/data/logs
FACEAI_PKL_ROOT=/data/pkl
FACEAI_MATCHER_BINARY=/opt/face-recognition/face_matcher
FACEAI_MATCHER_BINARY=/app/bin/face_matcher
```
If you want FaceAI to return through the new PHP bridge prepared under `www`, point `FACEAI_LEGACY_RETURN_URL` to that endpoint instead, for example `http://localhost/faceai_return.php` or the equivalent URL in your local PHP setup.
In the provided Docker Compose stack, that wiring is already done with:
In the development override, that wiring is already done with:
```text
FACEAI_LEGACY_RETURN_URL=http://localhost:8080/faceai_return.php
FACEAI_LEGACY_HOME_URL=http://localhost:8080/index.jsp
```
The log wiring is also already done in the checked-in Compose file with a host bind mount for `./logs:/data/logs`, so both the backend and the processor write persistent diagnostics into the workspace while also remaining visible through Docker and Portainer container logs.
The development override also keeps the log wiring with `./logs:/data/logs`, so both the backend and the processor write persistent diagnostics into the workspace while also remaining visible through Docker and Portainer container logs.
The Compose contract now also includes an HTTP healthcheck on the public FaceAI service and a Redis readiness check. That makes `docker compose ps` meaningful during rollout: `faceai` only becomes healthy after `GET /health` returns `{"ok":true}`, and both the public site and the processor wait for Redis readiness before their own startup sequence begins.
@ -491,12 +444,12 @@ The local PHP simulator also needs the legacy bridge feature flag enabled:
FACEAI_FEATURE_ENABLED=1
```
The checked-in `docker-compose.yml` now sets that on the `legacy-php` service so the simulator can launch the FaceAI handoff flow locally.
The checked-in `docker-compose.override.yml` sets that on the `legacy-php` service so the simulator can launch the FaceAI handoff flow locally.
## Notes
- Search orchestration now uses Redis and a dedicated processor worker.
- The checked-in Compose file is meant for local integration testing, not as-is production use.
- The checked-in base Compose file is production-oriented, while the checked-in override is development-only.
- The local legacy simulator is intentionally backend-driven so the handoff can be tested without compiling the existing Java application.
- `www/faceai_simulator.php` exists only for local testing. It does not replace the actual JSP race page.
- The final legacy integration still needs a real signed identity source and a real return-filter implementation on the old site.

View file

@ -0,0 +1,91 @@
services:
faceai:
image: ${FACEAI_CLIENT_DEV_IMAGE:-node:20-alpine}
working_dir: /app
command:
- node
- docker/run-with-log-file.mjs
- ${FACEAI_BACKEND_LOG_FILE:-/data/logs/backend.log}
- npm
- run
- start
- --workspace
- "@regalami/faceai-backend"
environment:
NODE_ENV: ${NODE_ENV:-development}
PORT: ${FACEAI_PORT:-3001}
FACEAI_FRONTEND_URL: ${FACEAI_FRONTEND_URL:-http://localhost:3001}
FACEAI_PUBLIC_BASE_URL: ${FACEAI_PUBLIC_BASE_URL:-http://localhost:3001}
FACEAI_LEGACY_RETURN_URL: ${FACEAI_LEGACY_RETURN_URL:-http://localhost:8080/faceai_return.php}
FACEAI_LEGACY_HOME_URL: ${FACEAI_LEGACY_HOME_URL:-http://localhost:8080/index.jsp}
FACEAI_SHARED_SECRET: ${FACEAI_SHARED_SECRET:-change-me}
FACEAI_SESSION_COOKIE: ${FACEAI_SESSION_COOKIE:-rus_faceai_session}
FACEAI_REDIS_URL: ${FACEAI_REDIS_URL:-redis://redis:6379}
FACEAI_QUEUE_NAME: ${FACEAI_QUEUE_NAME:-faceai-searches}
FACEAI_RUNTIME_ROOT: ${FACEAI_RUNTIME_ROOT:-/data/runtime}
FACEAI_UPLOAD_ROOT: ${FACEAI_UPLOAD_ROOT:-/data/runtime/uploads}
FACEAI_LOG_ROOT: ${FACEAI_LOG_ROOT:-/data/logs}
FACEAI_PKL_ROOT: ${FACEAI_PKL_ROOT:-/data/pkl}
FACEAI_ENABLE_LOCAL_LEGACY_STATIC: ${FACEAI_ENABLE_LOCAL_LEGACY_STATIC:-1}
FACEAI_LOCAL_LEGACY_STATIC_ROOT: ${FACEAI_LOCAL_LEGACY_STATIC_ROOT:-/legacy-www}
FACEAI_PROCESSOR_HEARTBEAT_GRACE_MS: ${FACEAI_PROCESSOR_HEARTBEAT_GRACE_MS:-20000}
volumes:
- .:/app
- ./logs:${FACEAI_LOG_ROOT:-/data/logs}
- ../www:${FACEAI_LOCAL_LEGACY_STATIC_ROOT:-/legacy-www}:ro
- ../test_pkl:${FACEAI_PKL_ROOT:-/data/pkl}:ro
- faceai-runtime:${FACEAI_RUNTIME_ROOT:-/data/runtime}
processor:
build:
context: ..
dockerfile: faceai/docker/processor.Dockerfile
image: ${FACEAI_PROCESSOR_DEV_IMAGE:-regalami-faceai-processor-local}
working_dir: /app
command:
- node
- docker/run-with-log-file.mjs
- ${FACEAI_PROCESSOR_LOG_FILE:-/data/logs/processor.log}
- npm
- run
- start
- --workspace
- "@regalami/faceai-processor"
environment:
NODE_ENV: ${NODE_ENV:-development}
FACEAI_REDIS_URL: ${FACEAI_REDIS_URL:-redis://redis:6379}
FACEAI_QUEUE_NAME: ${FACEAI_QUEUE_NAME:-faceai-searches}
FACEAI_RUNTIME_ROOT: ${FACEAI_RUNTIME_ROOT:-/data/runtime}
FACEAI_LOG_ROOT: ${FACEAI_LOG_ROOT:-/data/logs}
FACEAI_PKL_ROOT: ${FACEAI_PKL_ROOT:-/data/pkl}
FACEAI_MATCHER_BINARY: ${FACEAI_MATCHER_BINARY:-/app/bin/face_matcher}
FACEAI_WORKER_CONCURRENCY: ${FACEAI_WORKER_CONCURRENCY:-2}
FACEAI_WORKER_TIMEOUT_MS: ${FACEAI_WORKER_TIMEOUT_MS:-300000}
FACEAI_PROCESSOR_HEARTBEAT_INTERVAL_MS: ${FACEAI_PROCESSOR_HEARTBEAT_INTERVAL_MS:-5000}
FACEAI_PROCESSOR_HEARTBEAT_TTL_SECONDS: ${FACEAI_PROCESSOR_HEARTBEAT_TTL_SECONDS:-20}
volumes:
- ./logs:${FACEAI_LOG_ROOT:-/data/logs}
- ../test_pkl:${FACEAI_PKL_ROOT:-/data/pkl}:ro
- faceai-runtime:${FACEAI_RUNTIME_ROOT:-/data/runtime}
legacy-php:
image: ${FACEAI_LEGACY_PHP_IMAGE:-php:8.3-apache}
container_name: ${FACEAI_LEGACY_PHP_CONTAINER_NAME:-regalami-legacy-php}
restart: unless-stopped
environment:
FACEAI_FEATURE_ENABLED: ${FACEAI_FEATURE_ENABLED:-1}
FACEAI_BACKEND_INTERNAL_URL: ${FACEAI_BACKEND_INTERNAL_URL:-http://faceai:3001}
FACEAI_FRONTEND_URL: ${FACEAI_FRONTEND_URL:-http://localhost:3001}
FACEAI_SHARED_SECRET: ${FACEAI_SHARED_SECRET:-change-me}
FACEAI_ALLOW_DEV_HANDOFF: ${FACEAI_ALLOW_DEV_HANDOFF:-1}
FACEAI_IDENTITY_COOKIE: ${FACEAI_IDENTITY_COOKIE:-rus_faceai_identity}
volumes:
- ../www:/var/www/html
ports:
- "${FACEAI_LEGACY_PHP_PORT:-8080}:80"
depends_on:
faceai:
condition: service_healthy
volumes:
faceai-runtime:

View file

@ -1,44 +1,39 @@
services:
faceai:
image: node:20-alpine
container_name: regalami-faceai
image: ${FACEAI_CLIENT_IMAGE:-forgejo.maddoscientisto.net/maddo/faceai-client:latest}
container_name: ${FACEAI_CLIENT_CONTAINER_NAME:-regalami-faceai}
restart: unless-stopped
working_dir: /app
command:
- node
- docker/run-with-log-file.mjs
- /data/logs/backend.log
- ${FACEAI_BACKEND_LOG_FILE:-/data/logs/backend.log}
- npm
- run
- start
- --workspace
- "@regalami/faceai-backend"
environment:
PORT: 3001
FACEAI_FRONTEND_URL: http://localhost:3001
FACEAI_PUBLIC_BASE_URL: http://localhost:3001
FACEAI_LEGACY_RETURN_URL: http://localhost:8080/faceai_return.php
FACEAI_LEGACY_HOME_URL: http://localhost:8080/index.jsp
FACEAI_PKL_ROOT: /data/pkl
FACEAI_ENABLE_LOCAL_LEGACY_STATIC: 1
FACEAI_LOCAL_LEGACY_STATIC_ROOT: /legacy-www
FACEAI_SHARED_SECRET: disagio-spaghetti-science-lol-boh
FACEAI_SESSION_COOKIE: rus_faceai_session
FACEAI_REDIS_URL: redis://redis:6379
FACEAI_RUNTIME_ROOT: /data/runtime
FACEAI_UPLOAD_ROOT: /data/runtime/uploads
FACEAI_LOG_ROOT: /data/logs
FACEAI_PROCESSOR_HEARTBEAT_GRACE_MS: 20000
NODE_ENV: ${NODE_ENV:-production}
PORT: ${FACEAI_PORT:-3001}
FACEAI_FRONTEND_URL: ${FACEAI_FRONTEND_URL:-https://ai.regalamiunsorriso.it}
FACEAI_PUBLIC_BASE_URL: ${FACEAI_PUBLIC_BASE_URL:-https://ai.regalamiunsorriso.it}
FACEAI_LEGACY_RETURN_URL: ${FACEAI_LEGACY_RETURN_URL:-https://www.regalamiunsorriso.it/faceai_return.php}
FACEAI_LEGACY_HOME_URL: ${FACEAI_LEGACY_HOME_URL:-https://www.regalamiunsorriso.it}
FACEAI_SHARED_SECRET: ${FACEAI_SHARED_SECRET:-change-me}
FACEAI_SESSION_COOKIE: ${FACEAI_SESSION_COOKIE:-rus_faceai_session}
FACEAI_REDIS_URL: ${FACEAI_REDIS_URL:-redis://redis:6379}
FACEAI_QUEUE_NAME: ${FACEAI_QUEUE_NAME:-faceai-searches}
FACEAI_RUNTIME_ROOT: ${FACEAI_RUNTIME_ROOT:-/data/runtime}
FACEAI_UPLOAD_ROOT: ${FACEAI_UPLOAD_ROOT:-/data/runtime/uploads}
FACEAI_LOG_ROOT: ${FACEAI_LOG_ROOT:-/data/logs}
FACEAI_PKL_ROOT: ${FACEAI_PKL_ROOT:-/data/pkl}
FACEAI_ENABLE_LOCAL_LEGACY_STATIC: ${FACEAI_ENABLE_LOCAL_LEGACY_STATIC:-0}
volumes:
- .:/app
- ./logs:/data/logs
- ../www:/legacy-www:ro
- ../test_pkl:/data/pkl:ro
- faceai-runtime:/data/runtime
- ${FACEAI_RUNTIME_BIND:-/mnt/storage/data/faceai/runtime}:${FACEAI_RUNTIME_ROOT:-/data/runtime}
- ${FACEAI_LOG_BIND:-/mnt/storage/data/faceai/logs}:${FACEAI_LOG_ROOT:-/data/logs}
- ${FACEAI_PKL_BIND:-/mnt/nas12/nas2/RUS}:${FACEAI_PKL_ROOT:-/data/pkl}:ro
ports:
- "3001:3001"
- "${FACEAI_PUBLISHED_PORT:-3001}:${FACEAI_PORT:-3001}"
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3001/health').then(async (response) => { const payload = await response.json().catch(() => ({})); if (!response.ok || payload.ok !== true) { console.error(JSON.stringify(payload)); process.exit(1); } }).catch((error) => { console.error(error.stack || error.message); process.exit(1); })"]
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:' + (process.env.PORT || '3001') + '/health').then(async (response) => { const payload = await response.json().catch(() => ({})); if (!response.ok || payload.ok !== true) { console.error(JSON.stringify(payload)); process.exit(1); } }).catch((error) => { console.error(error.stack || error.message); process.exit(1); })"]
interval: 10s
timeout: 5s
retries: 6
@ -48,69 +43,41 @@ services:
condition: service_healthy
processor:
build:
context: ..
dockerfile: faceai/docker/processor.Dockerfile
image: regalami-faceai-processor-local
container_name: regalami-faceai-processor
image: ${FACEAI_PROCESSOR_IMAGE:-forgejo.maddoscientisto.net/maddo/faceai-processor:latest}
container_name: ${FACEAI_PROCESSOR_CONTAINER_NAME:-regalami-faceai-processor}
restart: unless-stopped
working_dir: /app
command:
- node
- docker/run-with-log-file.mjs
- /data/logs/processor.log
- ${FACEAI_PROCESSOR_LOG_FILE:-/data/logs/processor.log}
- npm
- run
- start
- --workspace
- "@regalami/faceai-processor"
- start:processor
environment:
FACEAI_REDIS_URL: redis://redis:6379
FACEAI_QUEUE_NAME: faceai-searches
FACEAI_RUNTIME_ROOT: /data/runtime
FACEAI_LOG_ROOT: /data/logs
FACEAI_PKL_ROOT: /data/pkl
FACEAI_WORKER_CONCURRENCY: 2
FACEAI_MATCHER_BINARY: /app/bin/face_matcher
FACEAI_PROCESSOR_HEARTBEAT_INTERVAL_MS: 5000
FACEAI_PROCESSOR_HEARTBEAT_TTL_SECONDS: 20
NODE_ENV: ${NODE_ENV:-production}
FACEAI_REDIS_URL: ${FACEAI_REDIS_URL:-redis://redis:6379}
FACEAI_QUEUE_NAME: ${FACEAI_QUEUE_NAME:-faceai-searches}
FACEAI_RUNTIME_ROOT: ${FACEAI_RUNTIME_ROOT:-/data/runtime}
FACEAI_LOG_ROOT: ${FACEAI_LOG_ROOT:-/data/logs}
FACEAI_PKL_ROOT: ${FACEAI_PKL_ROOT:-/data/pkl}
FACEAI_MATCHER_BINARY: ${FACEAI_MATCHER_BINARY:-/app/bin/face_matcher}
FACEAI_WORKER_CONCURRENCY: ${FACEAI_WORKER_CONCURRENCY:-8}
FACEAI_WORKER_TIMEOUT_MS: ${FACEAI_WORKER_TIMEOUT_MS:-300000}
volumes:
- ./logs:/data/logs
- ../test_pkl:/data/pkl:ro
- faceai-runtime:/data/runtime
- ${FACEAI_RUNTIME_BIND:-/mnt/storage/data/faceai/runtime}:${FACEAI_RUNTIME_ROOT:-/data/runtime}
- ${FACEAI_LOG_BIND:-/mnt/storage/data/faceai/logs}:${FACEAI_LOG_ROOT:-/data/logs}
- ${FACEAI_PKL_BIND:-/mnt/nas12/nas2/RUS}:${FACEAI_PKL_ROOT:-/data/pkl}:ro
depends_on:
redis:
condition: service_healthy
redis:
image: redis:7-alpine
container_name: regalami-faceai-redis
image: ${FACEAI_REDIS_IMAGE:-redis:7-alpine}
container_name: ${FACEAI_REDIS_CONTAINER_NAME:-regalami-faceai-redis}
restart: unless-stopped
command: redis-server --appendonly no
command: ${FACEAI_REDIS_COMMAND:-redis-server --appendonly no}
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 12
legacy-php:
image: php:8.3-apache
container_name: regalami-legacy-php
restart: unless-stopped
environment:
FACEAI_FEATURE_ENABLED: 1
FACEAI_BACKEND_INTERNAL_URL: http://faceai:3001
FACEAI_FRONTEND_URL: http://localhost:3001
FACEAI_SHARED_SECRET: disagio-spaghetti-science-lol-boh
FACEAI_ALLOW_DEV_HANDOFF: 1
FACEAI_IDENTITY_COOKIE: rus_faceai_identity
volumes:
- ../www:/var/www/html
ports:
- "8080:80"
depends_on:
faceai:
condition: service_healthy
volumes:
faceai-runtime:

View file

@ -11,6 +11,10 @@
"dev:backend": "npm run dev --workspace @regalami/faceai-backend",
"dev:frontend": "npm run dev --workspace @regalami/faceai-frontend",
"dev:processor": "npm run dev --workspace @regalami/faceai-processor",
"compose:prod:up": "docker compose -f docker-compose.yml --env-file .env.production up -d",
"compose:prod:down": "docker compose -f docker-compose.yml --env-file .env.production down",
"compose:dev:up": "docker compose --env-file .env.development up --build",
"compose:dev:down": "docker compose --env-file .env.development down",
"build": "npm run build --workspace @regalami/faceai-frontend && npm run build --workspace @regalami/faceai-backend",
"start": "npm run start --workspace @regalami/faceai-backend",
"start:processor": "npm run start --workspace @regalami/faceai-processor",

View file

@ -25,7 +25,6 @@ services:
FACEAI_UPLOAD_ROOT: /data/runtime/uploads
FACEAI_LOG_ROOT: /data/logs
FACEAI_PKL_ROOT: /data/pkl
FACEAI_PROCESSOR_HEARTBEAT_GRACE_MS: 20000
FACEAI_ENABLE_LOCAL_LEGACY_STATIC: 0
volumes:
- /mnt/storage/data/faceai/runtime:/data/runtime
@ -34,7 +33,7 @@ services:
ports:
- "3001:3001"
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3001/health').then(async (response) => { const payload = await response.json().catch(() => ({})); if (!response.ok || payload.ok !== true) { console.error(JSON.stringify(payload)); process.exit(1); } }).catch((error) => { console.error(error.stack || error.message); process.exit(1); })"]
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:3001/health | grep -q '\"ok\":true'"]
interval: 10s
timeout: 5s
retries: 6
@ -62,8 +61,6 @@ services:
FACEAI_LOG_ROOT: /data/logs
FACEAI_PKL_ROOT: /data/pkl
FACEAI_MATCHER_BINARY: /app/bin/face_matcher
FACEAI_PROCESSOR_HEARTBEAT_INTERVAL_MS: 5000
FACEAI_PROCESSOR_HEARTBEAT_TTL_SECONDS: 20
FACEAI_WORKER_CONCURRENCY: 8
FACEAI_WORKER_TIMEOUT_MS: 300000
volumes: