chore: productionize compose deployment
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
# Production Compose Design
|
||||
|
||||
**Goal:** Convert the current single-host `docker-compose` deployment from a development-oriented stack into a production-oriented stack while keeping the existing `docker-compose.yaml` as the only deployment entrypoint.
|
||||
|
||||
**Decisions**
|
||||
- Keep single-host `docker-compose` deployment.
|
||||
- Convert the frontend to a static build served directly by Nginx.
|
||||
- Keep PostgreSQL and the existing `pg_data` persistence model.
|
||||
- Keep one backend container and remove development-only runtime behavior.
|
||||
- Update the existing `docker-compose.yaml` in place instead of introducing a separate production file.
|
||||
|
||||
**Architecture**
|
||||
- `db` remains a long-lived PostgreSQL service with the existing bind-mounted data directory.
|
||||
- `backend` runs from the backend image default command and exposes only the application port needed inside the compose network.
|
||||
- `nginx` becomes the public entrypoint. It serves the built frontend assets and proxies `/api/` and `/health` to the backend service.
|
||||
- The frontend is no longer a long-running service in production. Its build artifacts are produced during the image build and copied into the Nginx image.
|
||||
|
||||
**Cleanup Scope**
|
||||
- Remove development-only compose services such as toolbox/init containers.
|
||||
- Remove development-only backend startup overrides such as `debugpy` and `uvicorn --reload`.
|
||||
- Remove development-only frontend runtime behavior such as `npm run dev`, bind mounts, and exposed Vite ports.
|
||||
- Keep data persistence and core service names stable where practical to limit operational change.
|
||||
|
||||
**Operational Notes**
|
||||
- Updating `docker-compose.yaml` in place means local development will no longer use the previous hot-reload setup by default.
|
||||
- Frontend SPA routing must be handled by Nginx with `try_files`.
|
||||
- Verification is done through `docker compose config`, image builds, container startup, and HTTP health checks.
|
||||
@@ -0,0 +1,110 @@
|
||||
# Production Compose Implementation Plan
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** Convert the repository's only `docker-compose.yaml` from development deployment to production deployment using static frontend assets served by Nginx.
|
||||
|
||||
**Architecture:** The backend runs as a production FastAPI container, the frontend is built into static assets during image build, and Nginx serves the SPA while reverse proxying backend routes. PostgreSQL remains persistent through the existing `pg_data` bind mount.
|
||||
|
||||
**Tech Stack:** Docker Compose, FastAPI, Vue/Vite, Nginx, PostgreSQL
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Productionize Frontend Image
|
||||
|
||||
**Files:**
|
||||
- Modify: `frontend/Dockerfile`
|
||||
|
||||
**Step 1: Replace dev runtime with a multi-stage production build**
|
||||
|
||||
Update the Dockerfile so a Node build stage runs dependency install and `npm run build`, then a lightweight stage exposes the built `dist` directory for downstream use instead of running `npm run dev`.
|
||||
|
||||
**Step 2: Keep the output suitable for Nginx consumption**
|
||||
|
||||
Ensure the final stage stores frontend assets in a predictable directory such as `/usr/share/nginx/html`.
|
||||
|
||||
**Step 3: Verify the image definition is syntactically valid**
|
||||
|
||||
Run: `docker compose config`
|
||||
Expected: compose renders successfully with no Dockerfile-related errors.
|
||||
|
||||
### Task 2: Productionize Nginx Runtime
|
||||
|
||||
**Files:**
|
||||
- Modify: `nginx/nginx.conf`
|
||||
|
||||
**Step 1: Add static frontend serving**
|
||||
|
||||
Set the web root to the built frontend assets and add `try_files $uri $uri/ /index.html;` for SPA routing.
|
||||
|
||||
**Step 2: Keep backend reverse proxy behavior**
|
||||
|
||||
Preserve `/api/` and `/health` proxying to `backend:8000` with standard forwarded headers.
|
||||
|
||||
**Step 3: Verify config structure through compose-backed startup**
|
||||
|
||||
Run: `docker compose config`
|
||||
Expected: compose renders successfully.
|
||||
|
||||
### Task 3: Productionize Compose Topology
|
||||
|
||||
**Files:**
|
||||
- Modify: `docker-compose.yaml`
|
||||
|
||||
**Step 1: Remove dev-only services and settings**
|
||||
|
||||
Delete `frontend`, `frontend-init`, and `backend-init`, and remove bind mounts, debug ports, and development commands that are only useful for hot reload or scaffolding.
|
||||
|
||||
**Step 2: Wire backend and nginx for production**
|
||||
|
||||
Allow the backend to use its Dockerfile default command, keep the database dependency, and expose only the ports needed for the production stack.
|
||||
|
||||
**Step 3: Build frontend assets into nginx**
|
||||
|
||||
Point the Nginx service build to a production image definition that includes the built frontend output.
|
||||
|
||||
**Step 4: Verify rendered compose**
|
||||
|
||||
Run: `docker compose config`
|
||||
Expected: only the production services remain and configuration renders cleanly.
|
||||
|
||||
### Task 4: Add Deployment Verification
|
||||
|
||||
**Files:**
|
||||
- Modify: `README.md`
|
||||
|
||||
**Step 1: Update deployment entry description**
|
||||
|
||||
Document that `docker-compose.yaml` is now the production deployment entrypoint.
|
||||
|
||||
**Step 2: Add minimal verification commands**
|
||||
|
||||
Document `docker compose up -d --build`, plus health checks for `/` and `/health`.
|
||||
|
||||
**Step 3: Verify behavior**
|
||||
|
||||
Run: `docker compose up -d --build`
|
||||
Expected: `db`, `backend`, and `nginx` start successfully.
|
||||
|
||||
### Task 5: End-to-End Verification
|
||||
|
||||
**Files:**
|
||||
- Verify only
|
||||
|
||||
**Step 1: Render final compose**
|
||||
|
||||
Run: `docker compose config`
|
||||
Expected: PASS
|
||||
|
||||
**Step 2: Start stack**
|
||||
|
||||
Run: `docker compose up -d --build`
|
||||
Expected: PASS
|
||||
|
||||
**Step 3: Check HTTP endpoints**
|
||||
|
||||
Run: `curl -i http://127.0.0.1/`
|
||||
Expected: `200 OK` and HTML payload
|
||||
|
||||
Run: `curl -i http://127.0.0.1/health`
|
||||
Expected: successful backend health response
|
||||
Reference in New Issue
Block a user