Improved Dockerfile
This commit is contained in:
67
AGENTS.md
Normal file
67
AGENTS.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# AGENTS.md
|
||||
|
||||
## Commands
|
||||
|
||||
```sh
|
||||
# Root (runs both frontend + backend)
|
||||
bun run dev
|
||||
|
||||
# Individual packages
|
||||
bun run dev:frontend
|
||||
bun run dev:backend
|
||||
bun run build:frontend
|
||||
|
||||
# Linting (Biome - ESLint was replaced)
|
||||
bun run lint
|
||||
bun run lint:fix # fixes and formats
|
||||
|
||||
# Prisma (run from backend)
|
||||
bun --filter backend prisma:generate # regenerate client after schema changes
|
||||
bun --filter backend prisma:migrate # apply migrations
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
apps/frontend/ # React + Vite + TanStack Router/Query
|
||||
apps/backend/ # Bun + Hono + Prisma
|
||||
packages/api-contract/ # Shared Zod schemas, types, route definitions
|
||||
```
|
||||
|
||||
**Shared contract pattern:**
|
||||
1. Update `packages/api-contract` first (schemas/types)
|
||||
2. Implement handler in `apps/backend`
|
||||
3. Consume from `apps/frontend` via workspace import `@repo/api-contract`
|
||||
|
||||
## Key Quirks
|
||||
|
||||
- **Prisma 7**: Uses `prisma.config.ts`, requires `DATABASE_URL` env var at generate time
|
||||
- **Zod v4**: Use `.issues` instead of `.errors` for validation errors
|
||||
- **Generated files**: `routeTree.gen.ts` and `tsconfig*.json` are auto-generated (ignored by Biome)
|
||||
- **TanStack Router**: Routes are code-generated. Use `--filter frontend build` not raw vite build.
|
||||
|
||||
## Docker Deployment (Dokploy)
|
||||
|
||||
- **Build Context**: `./` (monorepo root)
|
||||
- **Dockerfile**: `Dockerfile` (in root, not `apps/backend/`)
|
||||
- **Required args**: `DATABASE_URL`, `VITE_API_BASE_URL`, `VITE_SUPABASE_URL`, `VITE_SUPABASE_ANON_KEY`
|
||||
- **bun.lock must be tracked**: It's in `.gitignore` by default - remove it for Docker builds
|
||||
|
||||
## Linting
|
||||
|
||||
Biome is used (not ESLint). Config in `biome.json`:
|
||||
- Line width: 100
|
||||
- Quote style: single
|
||||
- Semicolons: always
|
||||
- `noUnusedVariables`: warn
|
||||
|
||||
## Environment Variables
|
||||
|
||||
**Backend** (`apps/backend/.env`):
|
||||
- `DATABASE_URL` - PostgreSQL connection (required for Prisma)
|
||||
- `SUPABASE_URL`, `SUPABASE_ANON_KEY` - Auth
|
||||
- `CORS_ORIGIN` - Frontend URL
|
||||
|
||||
**Frontend** (`apps/frontend/.env`):
|
||||
- `VITE_*` prefix required (Vite embeds these at build time)
|
||||
- `VITE_API_BASE_URL` - Backend URL (default: http://localhost:3000)
|
||||
59
Dockerfile
59
Dockerfile
@@ -1,39 +1,64 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
|
||||
FROM oven/bun:1.3 AS deps
|
||||
# =============================================================================
|
||||
# Stage 1: Install frontend dependencies
|
||||
# =============================================================================
|
||||
FROM oven/bun:1.3.11 AS deps-frontend
|
||||
WORKDIR /app
|
||||
COPY package.json bun.lock ./
|
||||
COPY apps/backend/package.json apps/backend/
|
||||
COPY apps/frontend/package.json apps/frontend/
|
||||
COPY packages/api-contract/package.json packages/api-contract/
|
||||
RUN bun install --frozen-lockfile
|
||||
RUN bun install
|
||||
|
||||
FROM deps AS build
|
||||
# =============================================================================
|
||||
# Stage 2: Build Frontend
|
||||
# =============================================================================
|
||||
FROM deps-frontend AS build-frontend
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
|
||||
COPY apps/frontend ./apps/frontend
|
||||
COPY packages ./packages
|
||||
ARG VITE_API_BASE_URL
|
||||
ARG VITE_SUPABASE_URL
|
||||
ARG VITE_SUPABASE_ANON_KEY
|
||||
ENV VITE_API_BASE_URL=${VITE_API_BASE_URL}
|
||||
ENV VITE_SUPABASE_URL=${VITE_SUPABASE_URL}
|
||||
ENV VITE_SUPABASE_ANON_KEY=${VITE_SUPABASE_ANON_KEY}
|
||||
|
||||
ARG DATABASE_URL=postgresql://placeholder:placeholder@placeholder:5432/placeholder
|
||||
ENV DATABASE_URL=${DATABASE_URL}
|
||||
|
||||
RUN bun run build:frontend
|
||||
RUN bun --cwd apps/backend prisma generate
|
||||
|
||||
FROM deps AS runner
|
||||
# =============================================================================
|
||||
# Stage 3: Install backend dependencies
|
||||
# =============================================================================
|
||||
FROM oven/bun:1.3.11 AS deps-backend
|
||||
WORKDIR /app
|
||||
COPY package.json bun.lock ./
|
||||
COPY apps/backend/package.json apps/backend/
|
||||
COPY packages/api-contract/package.json packages/api-contract/
|
||||
RUN bun install
|
||||
|
||||
# =============================================================================
|
||||
# Stage 4: Build Backend
|
||||
# =============================================================================
|
||||
FROM deps-backend AS build-backend
|
||||
WORKDIR /app
|
||||
COPY apps/backend ./apps/backend
|
||||
COPY packages ./packages
|
||||
RUN bun --cwd apps/backend build
|
||||
|
||||
# =============================================================================
|
||||
# Stage 5: Runner - Production image
|
||||
# =============================================================================
|
||||
FROM oven/bun:1.3.11 AS runner
|
||||
WORKDIR /app
|
||||
ENV NODE_ENV=production HOST=0.0.0.0 PORT=3000
|
||||
|
||||
COPY --from=build /app/node_modules ./node_modules
|
||||
COPY --from=build /app/apps/backend ./apps/backend
|
||||
COPY --from=build /app/packages ./packages
|
||||
COPY --from=deps-backend /app/node_modules ./node_modules
|
||||
COPY --from=build-frontend /app/apps/frontend/dist ./apps/frontend/dist
|
||||
COPY --from=build-backend /app/apps/backend ./apps/backend
|
||||
COPY --from=build-backend /app/packages ./packages
|
||||
COPY package.json ./
|
||||
COPY entrypoint.sh /app/entrypoint.sh
|
||||
|
||||
RUN chmod +x /app/entrypoint.sh
|
||||
|
||||
WORKDIR /app/apps/backend
|
||||
EXPOSE 3000
|
||||
CMD ["sh", "-lc", "bun run prisma migrate deploy && bun src/server.ts"]
|
||||
CMD ["/app/entrypoint.sh"]
|
||||
@@ -3,6 +3,7 @@
|
||||
"scripts": {
|
||||
"dev": "bun run --hot src/server.ts",
|
||||
"start": "bun src/server.ts",
|
||||
"build": "tsc -b",
|
||||
"lint": "biome check .",
|
||||
"lint:fix": "biome check --write .",
|
||||
"format": "biome format --write .",
|
||||
@@ -25,11 +26,11 @@
|
||||
"pino": "10.3.1",
|
||||
"pino-pretty": "13.1.3",
|
||||
"pino-std-serializers": "7.1.0",
|
||||
"prisma": "^7",
|
||||
"uuid": "^13.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest",
|
||||
"@types/nodemailer": "^8.0.0",
|
||||
"prisma": "^7"
|
||||
"@types/nodemailer": "^8.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
6
bun.lock
6
bun.lock
@@ -28,12 +28,12 @@
|
||||
"pino": "10.3.1",
|
||||
"pino-pretty": "13.1.3",
|
||||
"pino-std-serializers": "7.1.0",
|
||||
"prisma": "^7",
|
||||
"uuid": "^13.0.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest",
|
||||
"@types/nodemailer": "^8.0.0",
|
||||
"prisma": "^7",
|
||||
},
|
||||
},
|
||||
"apps/frontend": {
|
||||
@@ -571,7 +571,7 @@
|
||||
|
||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="],
|
||||
"@types/bun": ["@types/bun@1.3.12", "", { "dependencies": { "bun-types": "1.3.12" } }, "sha512-DBv81elK+/VSwXHDlnH3Qduw+KxkTIWi7TXkAeh24zpi5l0B2kUg9Ga3tb4nJaPcOFswflgi/yAvMVBPrxMB+A=="],
|
||||
|
||||
"@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
@@ -643,7 +643,7 @@
|
||||
|
||||
"browserslist": ["browserslist@4.28.2", "", { "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", "electron-to-chromium": "^1.5.328", "node-releases": "^2.0.36", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="],
|
||||
|
||||
"bun-types": ["bun-types@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="],
|
||||
"bun-types": ["bun-types@1.3.12", "", { "dependencies": { "@types/node": "*" } }, "sha512-HqOLj5PoFajAQciOMRiIZGNoKxDJSr6qigAttOX40vJuSp6DN/CxWp9s3C1Xwm4oH7ybueITwiaOcWXoYVoRkA=="],
|
||||
|
||||
"bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
|
||||
|
||||
|
||||
5
entrypoint.sh
Normal file
5
entrypoint.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
cd /app/apps/backend
|
||||
bun --cwd /app/apps/backend prisma migrate deploy
|
||||
bun --cwd /app/apps/backend prisma generate
|
||||
bun run start
|
||||
Reference in New Issue
Block a user