feat(T06): deployment config - Dockerfiles, docker-compose, Coolify guide, env example
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
# Coolify Deployment Configuration — ERP Nutzfahrzeuge
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes how to deploy the ERP Nutzfahrzeuge system on Coolify using Docker Compose.
|
||||
|
||||
The system consists of 4 services:
|
||||
|
||||
| Service | Image | Port | Health Check |
|
||||
|---------|-------|------|-------------|
|
||||
| Backend | Custom (Python 3.13-slim) | 8000 | `GET /api/v1/health` |
|
||||
| Frontend | Custom (Node 18-alpine) | 3000 | `GET /` |
|
||||
| PostgreSQL | `postgres:16-alpine` | 5432 | `pg_isready` |
|
||||
| Redis | `redis:7-alpine` | 6379 | `redis-cli ping` |
|
||||
|
||||
---
|
||||
|
||||
## Coolify Resource Setup
|
||||
|
||||
### Step 1: Create Resource
|
||||
|
||||
1. In Coolify, create a new resource
|
||||
2. Select **Docker Compose** as the resource type
|
||||
3. Connect your Forgejo/Git repository
|
||||
4. Set the base directory to the project root
|
||||
5. Coolify will detect `docker-compose.yml` automatically
|
||||
|
||||
### Step 2: Configure Environment Variables
|
||||
|
||||
1. Navigate to resource → **Environment Variables**
|
||||
2. Add all variables from `.env.example` (see `deploy/env.md` for descriptions)
|
||||
3. **Critical variables:**
|
||||
- `JWT_SECRET` — generate with `openssl rand -hex 32`
|
||||
- `POSTGRES_PASSWORD` — strong password for database
|
||||
- `CORS_ORIGINS` — production frontend URL (e.g., `https://erp.your-domain.com`)
|
||||
- `NEXT_PUBLIC_API_URL` — production backend URL (e.g., `https://api.your-domain.com/api/v1`)
|
||||
4. **Optional but feature-dependent:**
|
||||
- `OPENROUTER_API_KEY` — required for AI features (OCR, retouch, copilot)
|
||||
- `MOBILE_DE_API_KEY` + `MOBILE_DE_SELLER_ID` — required for mobile.de integration
|
||||
5. Click **Save** and redeploy
|
||||
|
||||
### Step 3: Configure Health Check
|
||||
|
||||
In the resource settings:
|
||||
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| Health check path | `/api/v1/health` |
|
||||
| Health check port | `8000` |
|
||||
| Health check interval | `30s` |
|
||||
| Health check timeout | `5s` |
|
||||
| Health check retries | `3` |
|
||||
|
||||
> **Note:** The health check targets the backend service. Docker Compose health checks are also defined per-service in `docker-compose.yml`.
|
||||
|
||||
### Step 4: Configure Persistent Storage
|
||||
|
||||
Docker Compose volumes are defined in `docker-compose.yml`:
|
||||
|
||||
| Volume | Mount Point | Purpose |
|
||||
|--------|-------------|---------|
|
||||
| `uploads` | `/data/uploads` (backend) | User file uploads (images, documents) |
|
||||
| `pgdata` | `/var/lib/postgresql/data` (postgres) | Database data |
|
||||
| `redisdata` | `/data` (redis) | Redis persistence (AOF) |
|
||||
|
||||
In Coolify:
|
||||
1. Ensure persistent storage is enabled for the resource
|
||||
2. Verify volume names match the compose file
|
||||
3. For production, consider using a managed PostgreSQL instance instead of the containerized one
|
||||
|
||||
### Step 5: Configure Domains / Routing
|
||||
|
||||
1. **Backend API:**
|
||||
- Set domain: `api.your-domain.com` (or subpath)
|
||||
- Port: `8000`
|
||||
- This is the primary entry point for Coolify health checks
|
||||
|
||||
2. **Frontend:**
|
||||
- Set domain: `erp.your-domain.com` (or root domain)
|
||||
- Port: `3000`
|
||||
- Next.js standalone server
|
||||
|
||||
3. **CORS:**
|
||||
- Set `CORS_ORIGINS` to the frontend domain
|
||||
- Set `NEXT_PUBLIC_API_URL` to the backend domain
|
||||
|
||||
### Step 6: Deploy
|
||||
|
||||
1. Click **Deploy** in Coolify
|
||||
2. Wait for all services to build and start
|
||||
3. Verify health checks pass (green status for all services)
|
||||
4. Test endpoints:
|
||||
- `GET https://api.your-domain.com/api/v1/health` → 200 `{"status":"ok"}`
|
||||
- `GET https://erp.your-domain.com/` → 200 (frontend loads)
|
||||
- `GET https://api.your-domain.com/openapi.json` → 200 (API schema)
|
||||
|
||||
---
|
||||
|
||||
## Coolify Service Type
|
||||
|
||||
- **Type:** Docker Compose (multi-service)
|
||||
- **Compose file:** `docker-compose.yml` (project root)
|
||||
- **Build:** Coolify builds images from `backend/Dockerfile` and `frontend/Dockerfile`
|
||||
- **Pre-built images:** `postgres:16-alpine`, `redis:7-alpine`
|
||||
|
||||
---
|
||||
|
||||
## Port Mapping
|
||||
|
||||
| Service | Internal Port | External Port | Notes |
|
||||
|---------|---------------|---------------|-------|
|
||||
| Backend | 8000 | 8000 | FastAPI + uvicorn (4 workers) |
|
||||
| Frontend | 3000 | 3000 | Next.js standalone server |
|
||||
| PostgreSQL | 5432 | — (internal only) | Not exposed externally |
|
||||
| Redis | 6379 | — (internal only) | Not exposed externally |
|
||||
|
||||
> In Coolify, only expose backend (8000) and frontend (3000) via domains. PostgreSQL and Redis should remain internal to the Docker network.
|
||||
|
||||
---
|
||||
|
||||
## Build Configuration
|
||||
|
||||
### Backend
|
||||
- **Base image:** `python:3.13-slim`
|
||||
- **System packages:** libpango, libcairo, libjpeg, libpng (for WeasyPrint + Pillow)
|
||||
- **Python venv:** `/opt/venv`
|
||||
- **Entry:** `uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4`
|
||||
|
||||
### Frontend
|
||||
- **Base image:** `node:18-alpine` (multi-stage)
|
||||
- **Build:** `npm ci && npm run build` (standalone output)
|
||||
- **Entry:** `node server.js`
|
||||
- **Requires:** `output: 'standalone'` in `next.config.js`
|
||||
|
||||
---
|
||||
|
||||
## Post-Deploy Verification
|
||||
|
||||
1. All 4 containers are running and healthy
|
||||
2. `GET /api/v1/health` → 200 `{"status":"ok"}`
|
||||
3. Frontend loads at production URL
|
||||
4. Login flow works: `POST /api/v1/auth/login`
|
||||
5. CORS headers present for frontend origin
|
||||
6. No errors in container logs
|
||||
7. File uploads work (test upload to `/data/uploads`)
|
||||
8. Database queries return expected data
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| Backend health check fails | DB not ready | Check `postgres` container health; increase `start_period` |
|
||||
| WeasyPrint errors | Missing system libs | Verify `libpango`, `libcairo` installed in backend image |
|
||||
| Frontend build fails | Missing `output: 'standalone'` | Add `output: 'standalone'` to `next.config.js` |
|
||||
| CORS errors | Wrong `CORS_ORIGINS` | Set to exact frontend domain (no trailing slash) |
|
||||
| AI features fail | Missing `OPENROUTER_API_KEY` | Set API key in Coolify environment variables |
|
||||
| mobile.de fails | Missing credentials | Set `MOBILE_DE_API_KEY` and `MOBILE_DE_SELLER_ID` |
|
||||
|
||||
---
|
||||
|
||||
## Rollback
|
||||
|
||||
See `deploy/rollback.md` for the full rollback procedure.
|
||||
|
||||
Quick rollback in Coolify:
|
||||
1. Navigate to resource → **Deployments**
|
||||
2. Find last known-good deployment
|
||||
3. Click **Redeploy**
|
||||
4. Verify health check passes
|
||||
Reference in New Issue
Block a user