# Docker — copy-only deploy (Dokploy) Build artifacts are produced **on the developer machine** and committed to git. Dokploy only builds thin images that copy those files (no `pnpm install` on the server). ## One-time / before each deploy ```bash pnpm install pnpm build:release git add -f apps/api/release apps/admin-panel/dist apps/user-app/dist git commit -m "chore: refresh release artifacts" git push ``` What this produces: | App | Artifact | Image | |---|---|---| | API | `apps/api/release/app.js` (+ Prisma under `release/vendor`) | `docker.arvancloud.ir/node:20-bookworm` | | Admin | `apps/admin-panel/dist/` | `docker.arvancloud.ir/nginx:latest` | | User | `apps/user-app/dist/` | `docker.arvancloud.ir/nginx:latest` | ## Dokploy Environment ```env POSTGRES_USER=hedenagold POSTGRES_PASSWORD=... POSTGRES_DB=hedenagold EXTERNAL_DB_PORT=5433 DATABASE_URL=postgresql://hedenagold:...@db:5432/hedenagold?schema=public PORT=3000 ``` A second copy on the **same server** is a separate Dokploy application (its own domains, passwords, and `JWT_SECRET`). Do not set `container_name` in this file: those names are global in Docker, and a fixed `hedenagold_db` collides with the first copy. Give the second app its own `EXTERNAL_DB_PORT` (for example `5434` if `5433` is already taken). Volumes stay separate because Dokploy uses a different Compose project name for each application. ## Domains (container ports) | Service | Domain | Port | |---|---|---| | `admin-panel` | admin.example.com | **80** | | `user-app` | app.example.com | **80** | | `api` | (optional) | **3000** | Frontends call `/api` on their own domain; nginx proxies to `api:3000`. ## Local compose smoke test ```bash pnpm build:release docker compose up --build -d ```