The repo ships a docker-compose.yml that brings up AppEngine plus its two dependencies. Five minutes from a clean checkout to a running instance.
What you get
Three services on a private Docker network:
appengine_<NODE_ENV>— the NestJS serverredis— cache, queuesmongodb— primary data store
Plus two named volumes (redis_data, mongodb_data) so data survives container restarts.
This setup is good for development, demos, and single-box production where the box is reliable. For real production with HA, see Kubernetes.
Prerequisites
- Docker Engine 24+ and Docker Compose v2
- 8 GB RAM minimum (4 for the AppEngine container, 2 for Mongo, 1 for Redis, 1 headroom)
- Repository access to
ghcr.io/appmint/appengine(or your custom image) - An NPM token if you're building from source against private packages
Step-by-step
- 1
Clone the repo (or pull the image)
If you have repo access:
git clone https://github.com/appmint/appengine.git cd appengineIf you only have the image, create an empty directory and skip ahead — you'll need only the compose file and an env file.
- 2
Build (or skip)
If you cloned the source, build the image:
docker compose build --build-arg NPM_TOKEN=$NPM_TOKENIf you're using a pre-built image from a registry, edit
docker-compose.ymland replace thebuild:block with:image: ghcr.io/appmint/appengine:latestThen
docker compose pull. - 3
Create the env file
Copy
src/envs/development.envto.envat the project root. The compose file reads${VAR}from there. The minimum vars Compose needs:# .env NODE_ENV=development SERVER_PORT=3300 REDIS_PORT=6379 REDIS_HOST=redis MONGODB_PORT=27017 MONGODB_HOST=mongodb MONGODB_USERNAME=admin MONGODB_PASSWORD=admin MONGODB_CONN=mongodb://admin:admin@mongodb:27017 REDIS_CONN=redis://redis:6379 ROOT_ORG=fundu ROOT_USER=admin ROOT_PASSWORD=changemepleaseimnotjokesayinnow [email protected]Plus your secrets — JWT, vendor APIs, OAuth — see Environment variables for the full list.
Don't ship development.env to productionThe shipped
development.envhas weak default secrets and live test API keys. Treat it as a starting structure, not a production template. Generate fresh JWT secrets withopenssl rand -base64 64. - 4
Start the stack
docker compose up -dFirst boot pulls or builds, runs
npm install(in dev mode), and starts. AppEngine waits for Mongo + Redis health, then runs schema migrations, then opens the port.Tail the logs:
docker compose logs -f appengineYou're ready when you see
Nest application successfully started.Hit the health endpoint:
curl http://localhost:3300/monitoring/health # {"status":"ok","mongodb":"up","redis":"up"} - 5
Sign in as the root user
The first boot creates the root org and user from the
ROOT_*env vars. Open a browser tohttp://localhost:3300(or front it with the websitemint admin).Use the credentials you set:
Org: fundu Email: [email protected] Password: changemepleaseimnotjokesayinnowChange the password in Settings → Profile after first login.
- 6
Persist data across rebuilds
The compose file already declares
mongodb_dataandredis_datavolumes — your data survivesdocker compose down. To wipe and start over:docker compose down -v # the -v deletes volumes, carefulFor backups,
mongodumpfrom a sidecar (ordocker exec mongodb mongodump):docker exec mongodb mongodump \ --uri "mongodb://admin:admin@localhost:27017" \ --out /backup/$(date +%Y%m%d)Mount a host directory into the mongo service's volumes so the dump lands somewhere you can rsync off the box.
Production-ish mode
The shipped compose runs npm run start:debug and mounts the source — that's a dev configuration. For a production-on-one-box setup:
# docker-compose.prod.yml
services:
appengine:
image: ghcr.io/appmint/appengine:1.x.x # pin a version
container_name: appengine_production
command: node dist/main.js
restart: unless-stopped
networks: [appmint-network]
environment:
NODE_ENV: production
SERVER_PORT: 3300
MEMORY_LIMIT: '4096'
env_file:
- .env.production
ports:
- '127.0.0.1:3300:3300' # bind to localhost; reverse-proxy in front
depends_on:
mongodb: { condition: service_healthy }
redis: { condition: service_healthy }
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:3300/monitoring/health']
interval: 30s
timeout: 5s
retries: 3
mongodb:
image: mongo:7
restart: unless-stopped
networks: [appmint-network]
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGODB_USERNAME}
MONGO_INITDB_ROOT_PASSWORD: ${MONGODB_PASSWORD}
volumes:
- mongodb_data:/data/db
healthcheck:
test: ['CMD', 'mongosh', '--eval', 'db.adminCommand(\"ping\")']
interval: 30s
timeout: 5s
retries: 3
redis:
image: redis:7
restart: unless-stopped
networks: [appmint-network]
command: ['redis-server', '--appendonly', 'yes']
volumes:
- redis_data:/data
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 30s
timeout: 5s
retries: 3
networks:
appmint-network: { driver: bridge }
volumes:
mongodb_data:
redis_data:
Run with:
docker compose -f docker-compose.prod.yml up -d
The differences from dev:
- Pinned image, no source mount, no debug command
- Health checks on every service, depends-on with health condition
- Restart on failure
- Mongo/Redis bound to internal network only — only AppEngine is exposed
- AppEngine bound to localhost — fronted by host nginx/Traefik/Caddy for TLS