Refactor application ports to 12000 for backend and 12001 for frontend; update documentation and configuration files accordingly
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -49,7 +49,7 @@ uvicorn app.main:app --reload --port 12000
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd frontend
|
cd frontend
|
||||||
flask --app app.main run --port 5000
|
flask --app app.main run --port 12001
|
||||||
```
|
```
|
||||||
|
|
||||||
### Running tests
|
### Running tests
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install system dependencies
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
gcc \
|
||||||
|
curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Copy requirements and install Python dependencies
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Copy application code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Expose port
|
||||||
|
EXPOSE 12000
|
||||||
|
|
||||||
|
# Run the application
|
||||||
|
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "12000"]
|
||||||
+1
-1
@@ -30,7 +30,7 @@ app = FastAPI(
|
|||||||
|
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
allow_origins=[os.getenv("CORS_ORIGINS", "http://localhost:5000")],
|
allow_origins=[os.getenv("CORS_ORIGINS", "http://localhost:12001")],
|
||||||
allow_credentials=True,
|
allow_credentials=True,
|
||||||
allow_methods=["*"],
|
allow_methods=["*"],
|
||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: ./backend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: ai-backend
|
||||||
|
ports:
|
||||||
|
- "12000:12000"
|
||||||
|
environment:
|
||||||
|
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
|
||||||
|
- JWT_SECRET=${JWT_SECRET}
|
||||||
|
- APP_URL=${APP_URL:-http://localhost}
|
||||||
|
- APP_NAME=${APP_NAME:-AI Allucanget}
|
||||||
|
- CORS_ORIGINS=${CORS_ORIGINS:-http://localhost:12001}
|
||||||
|
volumes:
|
||||||
|
- ./data:/app/data
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:12000/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 5s
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ./frontend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: ai-frontend
|
||||||
|
ports:
|
||||||
|
- "12001:12001"
|
||||||
|
environment:
|
||||||
|
- FLASK_SECRET_KEY=${FLASK_SECRET_KEY}
|
||||||
|
- BACKEND_URL=${BACKEND_URL:-http://backend:12000}
|
||||||
|
depends_on:
|
||||||
|
backend:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: ai-nginx
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./nginx/docker-compose.conf:/etc/nginx/conf.d/default.conf:ro
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
- frontend
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
|
||||||
|
networks:
|
||||||
|
app-network:
|
||||||
|
driver: bridge
|
||||||
+73
-11
@@ -8,13 +8,13 @@ Describes:
|
|||||||
## Infrastructure Level 1
|
## Infrastructure Level 1
|
||||||
|
|
||||||
```text
|
```text
|
||||||
┌─────────────────────────────────────────────┐
|
┌────────────────────────────────────────────┐
|
||||||
│ Host / VM │
|
│ Host / VM │
|
||||||
│ ┌─────────────┐ ┌─────────────────────┐ │
|
│ ┌─────────────┐ ┌────────────────────┐ │
|
||||||
│ │ frontend │ │ backend │ │
|
│ │ frontend │ │ backend │ │
|
||||||
│ │ (Flask) │ │ (FastAPI) │ │
|
│ │ (Flask) │ │ (FastAPI) │ │
|
||||||
│ │ :5000 │ │ :12000 │ │
|
│ │ :12001 │ │ :12000 │ │
|
||||||
│ └──────┬──────┘ └──────────┬──────────┘ │
|
│ └──────┬──────┘ └─────────┬──────────┘ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
│ └────────┬──────────┘ │
|
│ └────────┬──────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
@@ -22,7 +22,7 @@ Describes:
|
|||||||
│ │ db (DuckDB) │ │
|
│ │ db (DuckDB) │ │
|
||||||
│ │ data/app.db │ │
|
│ │ data/app.db │ │
|
||||||
│ └────────────────┘ │
|
│ └────────────────┘ │
|
||||||
└─────────────────────────────────────────────┘
|
└────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
**Motivation:** All three components run on a single VM (or as Docker containers) for simplicity and low operational overhead.
|
**Motivation:** All three components run on a single VM (or as Docker containers) for simplicity and low operational overhead.
|
||||||
@@ -33,12 +33,74 @@ Describes:
|
|||||||
|
|
||||||
| Building Block | Container / Process | Port |
|
| Building Block | Container / Process | Port |
|
||||||
| --------------- | ---------------------------- | ----- |
|
| --------------- | ---------------------------- | ----- |
|
||||||
| Flask frontend | `frontend` | 5000 |
|
| Flask frontend | `frontend` | 12001 |
|
||||||
| FastAPI backend | `backend` | 12000 |
|
| FastAPI backend | `backend` | 12000 |
|
||||||
| DuckDB | File on host (`data/app.db`) | — |
|
| DuckDB | File on host (`data/app.db`) | — |
|
||||||
|
|
||||||
## Infrastructure Level 2
|
## Infrastructure Level 2
|
||||||
|
|
||||||
### Docker Compose (alternative)
|
### Docker Compose (Recommended for Development & Production)
|
||||||
|
|
||||||
All three services can be run with `docker compose up`. The `backend` mounts the `data/` volume for DuckDB persistence.
|
All services are containerized and orchestrated with `docker compose`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ Docker Host / VM │
|
||||||
|
│ ┌──────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Docker Network: app-network (bridge) │ │
|
||||||
|
│ │ ┌──────────────────────────────────────────────┐ │ │
|
||||||
|
│ │ │ Backend Container (FastAPI) │ │ │
|
||||||
|
│ │ │ - Port: 12000 │ │ │
|
||||||
|
│ │ │ - Service Name: backend │ │ │
|
||||||
|
│ │ │ - Volume Mount: /app/data ← host/data/ │ │ │
|
||||||
|
│ │ ├──────────────────────────────────────────────┤ │ │
|
||||||
|
│ │ │ Frontend Container (Flask) │ │ │
|
||||||
|
│ │ │ - Port: 12001 │ │ │
|
||||||
|
│ │ │ - Service Name: frontend │ │ │
|
||||||
|
│ │ │ - Depends on: backend (health check) │ │ │
|
||||||
|
│ │ ├──────────────────────────────────────────────┤ │ │
|
||||||
|
│ │ │ Nginx Container (Reverse Proxy) │ │ │
|
||||||
|
│ │ │ - Port: 80 (HTTP), 443 (HTTPS) │ │ │
|
||||||
|
│ │ │ - Config: nginx/docker-compose.conf │ │ │
|
||||||
|
│ │ │ - Routes: /api/* → backend:12000 │ │ │
|
||||||
|
│ │ │ / → frontend:12001 │ │ │
|
||||||
|
│ │ └──────────────────────────────────────────────┘ │ │
|
||||||
|
│ └──────────────────────────────────────────────────────┘ │
|
||||||
|
│ ▲ │
|
||||||
|
│ Host Port Bindings │
|
||||||
|
│ 80:80, 443:443, 12000:12000, 12001:12001 │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
Users / Internet
|
||||||
|
```
|
||||||
|
|
||||||
|
**Deployment Steps:**
|
||||||
|
|
||||||
|
1. Ensure Docker and Docker Compose are installed
|
||||||
|
2. Create `.env` with required environment variables
|
||||||
|
3. Run: `docker compose up --build`
|
||||||
|
4. Access via browser at `http://localhost:12001` or through Nginx at `http://localhost:80`
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
|
||||||
|
- **Consistency**: Same containerized environment across development, testing, and production
|
||||||
|
- **Simplicity**: Single command to start entire stack
|
||||||
|
- **Portability**: Run on any system with Docker installed
|
||||||
|
- **Persistence**: DuckDB data survives container restarts via volume mounts
|
||||||
|
- **Networking**: Service names enable automatic DNS resolution (backend:12000, frontend:12001)
|
||||||
|
- **Observability**: Easy logging with `docker compose logs`
|
||||||
|
|
||||||
|
**See**: [Docker Compose Deployment Guide](./deployment/docker-compose.md) for detailed instructions.
|
||||||
|
|
||||||
|
### Coolify (Alternative for Existing Deployments)
|
||||||
|
|
||||||
|
If using Coolify instead of Docker Compose:
|
||||||
|
|
||||||
|
1. **Backend Service**: Nixpacks build with base directory `/backend`, port 12000
|
||||||
|
2. **Frontend Service**: Nixpacks build with base directory `/frontend`, port 12001
|
||||||
|
3. **Reverse Proxy**: Coolify's built-in proxy or custom Nginx config
|
||||||
|
4. **Data Persistence**: Volume mount at `/app/data` for DuckDB
|
||||||
|
|
||||||
|
**Note**: Both services must be on the same Coolify server or cluster for service-to-service communication via `http://localhost:12000` or service DNS names (depending on Coolify's networking setup).
|
||||||
|
|
||||||
|
**See**: [Coolify Deployment Guide](./deployment/coolify.md) for detailed instructions.
|
||||||
|
|||||||
@@ -2,6 +2,30 @@
|
|||||||
|
|
||||||
This guide covers deploying `ai.allucanget.biz` using [Coolify](https://coolify.io) from the repository `https://git.allucanget.biz/allucanget/ai.allucanget.biz.git`.
|
This guide covers deploying `ai.allucanget.biz` using [Coolify](https://coolify.io) from the repository `https://git.allucanget.biz/allucanget/ai.allucanget.biz.git`.
|
||||||
|
|
||||||
|
## Deployment Options
|
||||||
|
|
||||||
|
The application supports two deployment approaches:
|
||||||
|
|
||||||
|
### Option 1: Docker Compose (Recommended)
|
||||||
|
|
||||||
|
- **Best for**: Local development, consistent environments, simplified deployment
|
||||||
|
- **See**: [Docker Compose Deployment Guide](./docker-compose.md)
|
||||||
|
- **Key benefits**:
|
||||||
|
- Same containerized environment locally and in production
|
||||||
|
- Built-in service orchestration and networking
|
||||||
|
- Easy volume management for data persistence
|
||||||
|
- Better debugging and log viewing
|
||||||
|
|
||||||
|
### Option 2: Coolify with Nixpacks (Alternative)
|
||||||
|
|
||||||
|
- **Best for**: Existing Coolify installations, serverless deployments
|
||||||
|
- **Key differences**:
|
||||||
|
- Uses Coolify's Nixpacks build system instead of Docker
|
||||||
|
- Requires separate services setup in Coolify UI
|
||||||
|
- Manual environment variable configuration per service
|
||||||
|
|
||||||
|
This guide covers **Option 2 (Nixpacks)**. For **Option 1 (Docker Compose)**, see the [Docker Compose Deployment Guide](./docker-compose.md).
|
||||||
|
|
||||||
## Architecture Overview
|
## Architecture Overview
|
||||||
|
|
||||||
The application consists of two Python services:
|
The application consists of two Python services:
|
||||||
@@ -9,12 +33,12 @@ The application consists of two Python services:
|
|||||||
| Service | Framework | Port | Description |
|
| Service | Framework | Port | Description |
|
||||||
| -------- | ----------------- | ----- | ------------------------------------------ |
|
| -------- | ----------------- | ----- | ------------------------------------------ |
|
||||||
| Backend | FastAPI + uvicorn | 12000 | REST API, auth, AI generation, DuckDB |
|
| Backend | FastAPI + uvicorn | 12000 | REST API, auth, AI generation, DuckDB |
|
||||||
| Frontend | Flask + gunicorn | 5000 | SSR web UI, session auth, proxy to backend |
|
| Frontend | Flask + gunicorn | 12001 | SSR web UI, session auth, proxy to backend |
|
||||||
|
|
||||||
Coolify's built-in reverse proxy routes traffic:
|
Coolify's built-in reverse proxy routes traffic:
|
||||||
|
|
||||||
- `/api/*` → Backend (port 12000)
|
- `/api/*` → Backend (port 12000)
|
||||||
- `/` → Frontend (port 5000)
|
- `/` → Frontend (port 12001)
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
@@ -58,10 +82,10 @@ Add these as **Runtime** environment variables in Coolify:
|
|||||||
3. Choose the `main` branch
|
3. Choose the `main` branch
|
||||||
4. Set **Build Pack** to `nixpacks`
|
4. Set **Build Pack** to `nixpacks`
|
||||||
5. **CRITICAL: Set Base Directory to `/frontend`** — this tells Nixpacks to look in the `frontend/` subdirectory for `requirements.txt` and the Python application
|
5. **CRITICAL: Set Base Directory to `/frontend`** — this tells Nixpacks to look in the `frontend/` subdirectory for `requirements.txt` and the Python application
|
||||||
6. Set **Ports Exposed** to `5000`
|
6. Set **Ports Exposed** to `12001`
|
||||||
7. Set **Start Command** to:
|
7. Set **Start Command** to:
|
||||||
```txt
|
```txt
|
||||||
gunicorn app.main:app --bind 0.0.0.0:5000 --workers 2 --timeout 120
|
gunicorn app.main:app --bind 0.0.0.0:12001 --workers 2 --timeout 120
|
||||||
```
|
```
|
||||||
8. Click **Create Resource**
|
8. Click **Create Resource**
|
||||||
|
|
||||||
@@ -91,7 +115,7 @@ Coolify provides a built-in reverse proxy. Configure routing rules:
|
|||||||
### Frontend Proxy Rules
|
### Frontend Proxy Rules
|
||||||
|
|
||||||
- **Domain**: `ai.allucanget.biz`
|
- **Domain**: `ai.allucanget.biz`
|
||||||
- **Port**: `5000`
|
- **Port**: `12001`
|
||||||
- **Path**: `/` → forward to frontend
|
- **Path**: `/` → forward to frontend
|
||||||
|
|
||||||
### Nginx Configuration (Optional)
|
### Nginx Configuration (Optional)
|
||||||
@@ -113,7 +137,7 @@ location /api/ {
|
|||||||
|
|
||||||
# Frontend proxy
|
# Frontend proxy
|
||||||
location / {
|
location / {
|
||||||
proxy_pass http://frontend:5000;
|
proxy_pass http://frontend:12001;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
|||||||
@@ -0,0 +1,243 @@
|
|||||||
|
# Docker Compose Deployment Guide
|
||||||
|
|
||||||
|
This guide explains how to deploy the AI application locally using Docker Compose.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Docker Compose provides a convenient way to:
|
||||||
|
|
||||||
|
- **Develop locally** with the same containerized environment used in production
|
||||||
|
- **Manage services** as a single stack (backend, frontend, and Nginx)
|
||||||
|
- **Persist data** using volume mounts
|
||||||
|
- **Enable service-to-service communication** using Docker's internal networking
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Docker Desktop installed and running
|
||||||
|
- Docker Compose v2.0+ (included with Docker Desktop)
|
||||||
|
- A `.env` file with required environment variables (see [Configuration](#configuration))
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. **Clone the repository** and navigate to the project root:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ai.allucanget.biz
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Configure environment variables** in `.env`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy the example if you don't have a .env file
|
||||||
|
cp .env.example .env
|
||||||
|
|
||||||
|
# Edit .env and fill in required values
|
||||||
|
# - OPENROUTER_API_KEY: Your openrouter.ai API key
|
||||||
|
# - JWT_SECRET: A random secret for signing JWT tokens
|
||||||
|
# - FLASK_SECRET_KEY: A random secret for Flask session cookies
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Build and start the services**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Access the application**:
|
||||||
|
- Frontend UI: http://localhost:12001
|
||||||
|
- Backend API: http://localhost:12000
|
||||||
|
- API Health: http://localhost:12000/health
|
||||||
|
- Nginx Proxy: http://localhost:80 (routes to frontend) or http://localhost:80/api (routes to backend)
|
||||||
|
|
||||||
|
5. **View logs**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# All services
|
||||||
|
docker compose logs -f
|
||||||
|
|
||||||
|
# Specific service
|
||||||
|
docker compose logs -f backend
|
||||||
|
docker compose logs -f frontend
|
||||||
|
```
|
||||||
|
|
||||||
|
6. **Stop the services**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
The `.env` file in the project root is automatically loaded by Docker Compose. Required variables:
|
||||||
|
|
||||||
|
| Variable | Purpose | Example |
|
||||||
|
| -------------------- | ------------------------------------------ | ---------------------------------------------------------------------------- |
|
||||||
|
| `OPENROUTER_API_KEY` | API key for AI generation | `sk-or-v1-...` |
|
||||||
|
| `JWT_SECRET` | Secret for JWT token signing | (random hex string) |
|
||||||
|
| `FLASK_SECRET_KEY` | Secret for Flask session cookies | (random hex string) |
|
||||||
|
| `BACKEND_URL` | Internal URL for frontend to reach backend | `http://backend:12000` (Docker) or `http://localhost:12000` (local dev) |
|
||||||
|
| `CORS_ORIGINS` | Allowed CORS origins for backend | `http://localhost:12001` (local) or `https://ai.allucanget.biz` (production) |
|
||||||
|
| `APP_URL` | Public URL of the backend | `http://localhost` or `https://ai.allucanget.biz` |
|
||||||
|
| `APP_NAME` | Application name | `AI Allucanget` |
|
||||||
|
|
||||||
|
### Volume Mounts
|
||||||
|
|
||||||
|
The `docker-compose.yml` defines the following volume:
|
||||||
|
|
||||||
|
- `./data:/app/data` — Persists the DuckDB database (`app.db`) between container restarts
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ Docker Network: app-network (internal bridge) │
|
||||||
|
├─────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ ┌──────────────────┐ ┌──────────────────────────┐ │
|
||||||
|
│ │ Frontend │ │ Backend │ │
|
||||||
|
│ │ Port 12001 │ │ Port 12000 │ │
|
||||||
|
│ │ Flask + Gunicorn│◄──►│ FastAPI + Uvicorn │ │
|
||||||
|
│ │ (Service name: │ │ (Service name: backend) │ │
|
||||||
|
│ │ frontend) │ │ │ │
|
||||||
|
│ └──────────────────┘ │ ┌────────────────────┐ │ │
|
||||||
|
│ ▲ │ │ DuckDB Database │ │ │
|
||||||
|
│ │ │ │ /app/data/app.db │ │ │
|
||||||
|
│ ┌────▼──────────────┐ │ └────────────────────┘ │ │
|
||||||
|
│ │ Nginx (Port 80) │ └──────────────────────────┘ │
|
||||||
|
│ │ Reverse Proxy │ │
|
||||||
|
│ └───────────────────┘ │
|
||||||
|
│ ▲ │
|
||||||
|
│ │ (bind mount) │
|
||||||
|
│ Host:80, 443 │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
Host OS
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Tasks
|
||||||
|
|
||||||
|
### View service status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose ps
|
||||||
|
```
|
||||||
|
|
||||||
|
Output example:
|
||||||
|
|
||||||
|
```
|
||||||
|
NAME COMMAND SERVICE STATUS PORTS
|
||||||
|
ai-backend "uvicorn app.main:a…" backend Up 2m 0.0.0.0:12000->12000/tcp
|
||||||
|
ai-frontend "gunicorn app.main:…" frontend Up 2m 0.0.0.0:12001->12001/tcp
|
||||||
|
ai-nginx "nginx -g daemon of…" nginx Up 2m 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rebuild images
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Rebuild all services
|
||||||
|
docker compose build
|
||||||
|
|
||||||
|
# Rebuild a specific service
|
||||||
|
docker compose build backend
|
||||||
|
docker compose build frontend
|
||||||
|
```
|
||||||
|
|
||||||
|
### Access container shell
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backend shell
|
||||||
|
docker compose exec backend bash
|
||||||
|
|
||||||
|
# Frontend shell
|
||||||
|
docker compose exec frontend bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### View service logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Tail all logs
|
||||||
|
docker compose logs -f
|
||||||
|
|
||||||
|
# Follow only backend logs
|
||||||
|
docker compose logs -f backend
|
||||||
|
|
||||||
|
# Last 100 lines of frontend logs
|
||||||
|
docker compose logs --tail 100 frontend
|
||||||
|
```
|
||||||
|
|
||||||
|
### Clean up
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Stop containers but keep volumes and images
|
||||||
|
docker compose stop
|
||||||
|
|
||||||
|
# Stop and remove containers
|
||||||
|
docker compose down
|
||||||
|
|
||||||
|
# Stop containers and remove volumes (WARNING: deletes database!)
|
||||||
|
docker compose down -v
|
||||||
|
|
||||||
|
# Remove images as well
|
||||||
|
docker compose down --rmi all
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "Docker daemon is not running"
|
||||||
|
|
||||||
|
**Error**: `error during connect: This error may indicate the client is not properly configured`
|
||||||
|
|
||||||
|
**Solution**: Start Docker Desktop (Windows/Mac) or start the Docker daemon (Linux).
|
||||||
|
|
||||||
|
### "Port 12000 or 12001 already in use"
|
||||||
|
|
||||||
|
**Error**: `Error response from daemon: bind: address already in use`
|
||||||
|
|
||||||
|
**Solution**: Either stop the other application using that port, or modify the ports in `docker-compose.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
ports:
|
||||||
|
- "13000:12000" # Maps host:13000 to container:12000
|
||||||
|
- "13001:12001" # Maps host:13001 to container:12001
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frontend cannot reach backend
|
||||||
|
|
||||||
|
**Error**: Connection refused or 502 Bad Gateway
|
||||||
|
|
||||||
|
**Ensure**:
|
||||||
|
|
||||||
|
1. Backend service is running: `docker compose ps`
|
||||||
|
2. `BACKEND_URL` in `.env` is set to `http://backend:12000` (not `localhost`)
|
||||||
|
3. Services are on the same Docker network: `docker compose ps` shows them in the same `docker-compose.yml`
|
||||||
|
|
||||||
|
### Database file not persisting
|
||||||
|
|
||||||
|
**Issue**: Data is lost after `docker compose down`
|
||||||
|
|
||||||
|
**Solution**: The volume mount `./data:/app/data` should persist data automatically. Check that:
|
||||||
|
|
||||||
|
1. The `data/` directory exists on your host
|
||||||
|
2. The volume is mounted correctly in `docker-compose.yml`
|
||||||
|
3. DuckDB has write permissions to the `data/` directory
|
||||||
|
|
||||||
|
## Performance Tips
|
||||||
|
|
||||||
|
- **Development**: Use `docker compose up` for real-time logs and quick iterations
|
||||||
|
- **Background**: Use `docker compose up -d` to run services detached
|
||||||
|
- **Rebuilds**: Use `docker compose up --build` only when dependencies or Dockerfiles change
|
||||||
|
- **Caching**: Docker caches layers; unchanged steps build faster
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
- **Deployment**: See [Coolify Deployment](./coolify.md) for production deployment
|
||||||
|
- **Testing**: See [Testing Guide](../TESTING.md) for running tests
|
||||||
|
- **Architecture**: See [Deployment View](../7-deployment-view.md) for system architecture
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
|
- [Docker Compose Documentation](https://docs.docker.com/compose/)
|
||||||
|
- [Docker Networking Guide](https://docs.docker.com/network/)
|
||||||
|
- [Best Practices for Writing Dockerfiles](https://docs.docker.com/develop/dev-best-practices/dockerfile_best-practices/)
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install system dependencies
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
gcc \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Copy requirements and install Python dependencies
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Copy application code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Expose port
|
||||||
|
EXPOSE 12001
|
||||||
|
|
||||||
|
# Run the application
|
||||||
|
CMD ["gunicorn", "app.main:app", "--bind", "0.0.0.0:12001", "--workers", "2", "--timeout", "120"]
|
||||||
@@ -79,6 +79,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Video polling error:", e);
|
console.error("Video polling error:", e);
|
||||||
}
|
}
|
||||||
}, 5000);
|
}, 12001);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ upstream backend {
|
|||||||
|
|
||||||
# Frontend proxy
|
# Frontend proxy
|
||||||
upstream frontend {
|
upstream frontend {
|
||||||
server 127.0.0.1:5000;
|
server 127.0.0.1:12001;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# Nginx reverse proxy configuration for Docker Compose deployment
|
||||||
|
# Place this in docker-compose.yml volume mount to /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# Backend API proxy - use Docker service name instead of localhost
|
||||||
|
upstream backend {
|
||||||
|
server backend:12000;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Frontend proxy - use Docker service name instead of localhost
|
||||||
|
upstream frontend {
|
||||||
|
server frontend:12001;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
# Backend API proxy
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://backend;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# WebSocket support (if needed in future)
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Frontend proxy
|
||||||
|
location / {
|
||||||
|
proxy_pass http://frontend;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# Static files caching
|
||||||
|
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
proxy_pass http://frontend;
|
||||||
|
expires 30d;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Health check endpoint
|
||||||
|
location /health {
|
||||||
|
proxy_pass http://backend;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user