How to deploy
Emotial runs as four Docker containers on one network: web, api, postgres, and minio. That is how production runs on Slater's server. The live site is https://emotial.app.
The Dockerfiles are source/web/Dockerfile and source/api/Dockerfile. source/docker-compose.yml starts all four.
What you need
- Docker with Compose
- About 4 GB of disk for the images
Start the stack
From submission/source/:
- Start Postgres and MinIO.
docker compose up -d postgres minio
- Apply the schema. The API connects to Postgres but does not create tables.
docker compose exec -T postgres psql -U emotial -d emotial -v ON_ERROR_STOP=1 < schema.sql
- Build and start the API and web app.
docker compose up -d --build api web
- Open http://localhost:3000. Create an account using the login instructions.
| Service | URL |
|---|---|
| Web | http://localhost:3000 |
| API health | http://localhost:8080/health |
| MinIO API (media) | http://localhost:9000 |
| MinIO console | http://localhost:9001 |
MinIO console: user emotial, password emotial-minio-secret. The API creates the emotial bucket when it starts.
Stop
docker compose down
Add -v if you want to delete the Postgres and MinIO volumes too.
How the containers talk
The browser loads the web app on port 3000 and calls the API on port 8080.
The API reaches Postgres as hostname postgres and MinIO as minio:9000.
Browsers load uploaded images from http://localhost:9000/emotial/... (path-style), not from the Docker hostname.
NEXT_PUBLIC_API_BASE_URL is set when the web image is built. If you change the public API URL, rebuild web.
Production notes
On a public host, change these in the compose file (or whatever you use to run it) before you go live:
EMOTIAL_SERVER_ALLOW_ORIGINSandEMOTIAL_SERVER_APP_URLtohttps://your-domain- Web build args
NEXT_PUBLIC_APP_URLandNEXT_PUBLIC_API_BASE_URLto those public URLs EMOTIAL_AUTH_JWT_SECRETto a new value (openssl rand -hex 32)EMOTIAL_AUTH_SECURE_COOKIEStotrueEMOTIAL_MEDIA_PUBLIC_URLto the URL browsers use for objects (a CDN origin, or the published MinIO host)- Postgres and MinIO passwords
The API image build compiles with libvips (HEIF/AVIF) and runs the media tests during docker build.