109 lines
4.1 KiB
Markdown
109 lines
4.1 KiB
Markdown
|
|
---
|
||
|
|
phase: 17-docker-deployment
|
||
|
|
plan: 01
|
||
|
|
subsystem: infra
|
||
|
|
tags: [docker, nextjs, standalone, neon, postgres, health-check]
|
||
|
|
|
||
|
|
# Dependency graph
|
||
|
|
requires:
|
||
|
|
- phase: 01-foundation
|
||
|
|
provides: db/index.ts lazy singleton and Drizzle setup
|
||
|
|
provides:
|
||
|
|
- next.config.ts with output standalone for Docker three-stage build
|
||
|
|
- db connection pool capped at 5 for Neon free tier
|
||
|
|
- GET /api/health endpoint for Docker HEALTHCHECK directive
|
||
|
|
- @vercel/blob dead dependency removed from package.json
|
||
|
|
affects: [17-02-docker-files, Dockerfile, docker-compose.yml]
|
||
|
|
|
||
|
|
# Tech tracking
|
||
|
|
tech-stack:
|
||
|
|
added: []
|
||
|
|
patterns:
|
||
|
|
- "Health endpoint pattern: public GET /api/health with SELECT 1 DB ping, 200/503 response"
|
||
|
|
- "Neon pool limit: postgres(url, { max: 5 }) leaves headroom for migrations on free tier"
|
||
|
|
|
||
|
|
key-files:
|
||
|
|
created:
|
||
|
|
- teressa-copeland-homes/src/app/api/health/route.ts
|
||
|
|
modified:
|
||
|
|
- teressa-copeland-homes/next.config.ts
|
||
|
|
- teressa-copeland-homes/src/lib/db/index.ts
|
||
|
|
- teressa-copeland-homes/package.json
|
||
|
|
|
||
|
|
key-decisions:
|
||
|
|
- "output: 'standalone' added to next.config.ts — required for Dockerfile three-stage build to produce self-contained server.js"
|
||
|
|
- "postgres pool max: 5 — Neon free tier allows 10 connections; 5 leaves headroom for migrations and overlapping deploys"
|
||
|
|
- "@vercel/blob removed — confirmed not imported anywhere in src/; BLOB_READ_WRITE_TOKEN excluded from .env.production.example"
|
||
|
|
- "Health endpoint is intentionally public (no auth) so Docker HEALTHCHECK can reach it without credentials"
|
||
|
|
|
||
|
|
patterns-established:
|
||
|
|
- "Health check: SELECT 1 via Drizzle sql template tag, wrapped in try/catch, 200 ok / 503 error"
|
||
|
|
|
||
|
|
requirements-completed: [DEPLOY-01, DEPLOY-02, DEPLOY-04]
|
||
|
|
|
||
|
|
# Metrics
|
||
|
|
duration: 2min
|
||
|
|
completed: 2026-04-03
|
||
|
|
---
|
||
|
|
|
||
|
|
# Phase 17 Plan 01: Docker Deployment Prep Summary
|
||
|
|
|
||
|
|
**Standalone Next.js output, Neon pool cap at 5, @vercel/blob removal, and public GET /api/health endpoint with SELECT 1 DB check**
|
||
|
|
|
||
|
|
## Performance
|
||
|
|
|
||
|
|
- **Duration:** 2 min
|
||
|
|
- **Started:** 2026-04-03T22:52:56Z
|
||
|
|
- **Completed:** 2026-04-03T22:53:49Z
|
||
|
|
- **Tasks:** 2
|
||
|
|
- **Files modified:** 4
|
||
|
|
|
||
|
|
## Accomplishments
|
||
|
|
|
||
|
|
- Added `output: 'standalone'` to `next.config.ts` (prerequisite for Dockerfile three-stage build)
|
||
|
|
- Limited Neon postgres pool to `max: 5` in `src/lib/db/index.ts` to prevent connection exhaustion on free tier
|
||
|
|
- Removed dead `@vercel/blob` dependency (7 packages removed, confirmed not imported anywhere in src/)
|
||
|
|
- Created `GET /api/health` at `src/app/api/health/route.ts` — runs `SELECT 1` via Drizzle, returns 200 or 503
|
||
|
|
|
||
|
|
## Task Commits
|
||
|
|
|
||
|
|
Each task was committed atomically:
|
||
|
|
|
||
|
|
1. **Task 1: Enable standalone output, limit DB pool, remove @vercel/blob** - `fa7d6a9` (feat)
|
||
|
|
2. **Task 2: Create /api/health endpoint with DB connectivity check** - `57326d7` (feat)
|
||
|
|
|
||
|
|
## Files Created/Modified
|
||
|
|
|
||
|
|
- `teressa-copeland-homes/next.config.ts` - Added `output: 'standalone'`; kept existing `transpilePackages` and `serverExternalPackages`
|
||
|
|
- `teressa-copeland-homes/src/lib/db/index.ts` - Changed `postgres(url)` to `postgres(url, { max: 5 })`
|
||
|
|
- `teressa-copeland-homes/package.json` - Removed `@vercel/blob: ^2.3.1` from dependencies
|
||
|
|
- `teressa-copeland-homes/src/app/api/health/route.ts` - New public GET endpoint, SELECT 1 via Drizzle, 200/503 response
|
||
|
|
|
||
|
|
## Decisions Made
|
||
|
|
|
||
|
|
- Health endpoint is intentionally public (no auth import, no session check) so Docker HEALTHCHECK can reach it without credentials
|
||
|
|
- Kept `transpilePackages` and `serverExternalPackages` intact in next.config.ts per plan spec
|
||
|
|
|
||
|
|
## Deviations from Plan
|
||
|
|
|
||
|
|
None - plan executed exactly as written.
|
||
|
|
|
||
|
|
## Issues Encountered
|
||
|
|
|
||
|
|
None — TypeScript compiled clean (`npx tsc --noEmit` passed with no output).
|
||
|
|
|
||
|
|
## User Setup Required
|
||
|
|
|
||
|
|
None - no external service configuration required.
|
||
|
|
|
||
|
|
## Next Phase Readiness
|
||
|
|
|
||
|
|
- Plan 17-02 (Dockerfile, docker-compose.yml, .dockerignore, .env.production.example) can proceed immediately
|
||
|
|
- All code-level prerequisites for the Docker build are now in place
|
||
|
|
- Dockerfile builder stage will find `output: 'standalone'` in next.config.ts
|
||
|
|
- `docker-compose.yml` HEALTHCHECK can target `http://localhost:3000/api/health`
|
||
|
|
|
||
|
|
---
|
||
|
|
*Phase: 17-docker-deployment*
|
||
|
|
*Completed: 2026-04-03*
|