Docker
The backend ships as a multi-stage Docker image. See marketplace-fleapoai-service/Dockerfile.
Stages
| Stage | Purpose |
|---|---|
development | Full dev deps + ts-node. Used for one-off CI tasks. |
build | pnpm install --frozen-lockfile && pnpm build → emits dist/. |
production | Slim runtime: copies dist/, node_modules/ (prod-only), drizzle/, docker-entrypoint.sh. Node 22-alpine base. |
Three-stage keeps the final image small while reusing layer cache aggressively.
docker-entrypoint.sh
#!/bin/sh
set -e
node dist/src/db/migrate.js
node dist/seed.js
exec node dist/src/main.js
Runs on every container start. Migrations and seed are idempotent — re-running them is a no-op.
Build args
| Arg | Used for |
|---|---|
GIT_SHA | Baked into ENV; surfaced at GET /health |
RELEASE_VERSION | Baked into ENV; surfaced at GET /health |
docker build \
--build-arg GIT_SHA=$(git rev-parse HEAD) \
--build-arg RELEASE_VERSION=v1.2.3 \
-t marketplace:v1.2.3 .
Node version
node:22-alpine. Do not downgrade.
- better-auth uses global
crypto(Node 18+). - posthog-node likewise.
If you need a different distro (e.g. slim for native deps), update the FROM but keep the major version.
drizzle/ in production
The production stage copies drizzle/ (the SQL migration files + meta/_journal.json) so the migrator can resolve files at process.cwd()/drizzle at runtime. If you forget this COPY, the entrypoint will fail with Cannot find migrations folder.
ENV at runtime
ECS / Fargate / Kubernetes inject env vars into the container. The image itself ships with no production secrets. See Config & env vars.
Building for AWS Fargate
Apple Silicon developers must cross-build to amd64:
docker buildx build --platform linux/amd64 -t marketplace:v1.2.3 .
Otherwise you'll get exec format error on Fargate startup.
Local one-shot
docker build -t marketplace:dev .
docker run -p 3000:3000 --env-file .env marketplace:dev
Image size
Roughly 220 MB at time of writing. Most of that is node_modules/ from better-auth, drizzle-orm, posthog-node, @nestjs/*. Don't chase smaller without measuring — the migration runner needs everything.