From fe32c3272621028df49f4b1f693f7e426ea84038 Mon Sep 17 00:00:00 2001 From: zwitschi Date: Wed, 29 Apr 2026 13:24:58 +0200 Subject: [PATCH] Remove Docker Compose configuration files and update deployment documentation for Coolify with Nixpacks Co-authored-by: Copilot --- README.md | 16 ++ docker-compose.coolify.yml | 45 ------ docker-compose.yml | 58 ------- docs/7-deployment-view.md | 81 +++------- docs/deployment/coolify.md | 225 ++++++++++++++++++--------- docs/deployment/docker-compose.md | 243 ------------------------------ nginx/docker-compose.conf | 53 ------- 7 files changed, 192 insertions(+), 529 deletions(-) delete mode 100644 docker-compose.coolify.yml delete mode 100644 docker-compose.yml delete mode 100644 docs/deployment/docker-compose.md delete mode 100644 nginx/docker-compose.conf diff --git a/README.md b/README.md index 6c303be..ce23eca 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,22 @@ flask --app app.main run --port 12016 pytest ``` +## Default admin user + +On first startup a default admin account is created: + +| Field | Value | +| -------- | ------------------- | +| Email | `ai@allucanget.biz` | +| Password | `admin123` | +| Role | `admin` | + +Override via environment variables `ADMIN_EMAIL` and `ADMIN_PASSWORD` before first run. + +## Deployment + +Deployed on [Coolify](https://coolify.io) using Nixpacks. See [docs/deployment/coolify.md](docs/deployment/coolify.md) for full instructions. + ## Project Structure ```txt diff --git a/docker-compose.coolify.yml b/docker-compose.coolify.yml deleted file mode 100644 index 2974b4e..0000000 --- a/docker-compose.coolify.yml +++ /dev/null @@ -1,45 +0,0 @@ -services: - backend: - build: - context: ./backend - dockerfile: Dockerfile - environment: - - OPENROUTER_API_KEY=${OPENROUTER_API_KEY} - - JWT_SECRET=${JWT_SECRET} - - APP_URL=${APP_URL:-https://ai.allucanget.biz} - - APP_NAME=${APP_NAME:-All You Can GET AI} - - CORS_ORIGINS=${CORS_ORIGINS:-https://ai.allucanget.biz} - volumes: - - app-data:/app/data - networks: - - app-network - healthcheck: - test: [ "CMD", "curl", "-f", "http://localhost:12015/health" ] - interval: 30s - timeout: 10s - retries: 3 - start_period: 5s - expose: - - "12015" - - frontend: - build: - context: ./frontend - dockerfile: Dockerfile - environment: - - FLASK_SECRET_KEY=${FLASK_SECRET_KEY} - - BACKEND_URL=${BACKEND_URL:-http://backend:12015} - depends_on: - backend: - condition: service_healthy - networks: - - app-network - expose: - - "12016" - -networks: - app-network: - driver: bridge - -volumes: - app-data: diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 74e954d..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,58 +0,0 @@ -services: - backend: - build: - context: ./backend - dockerfile: Dockerfile - container_name: ai-backend - ports: - - "12015:12015" - environment: - - OPENROUTER_API_KEY=${OPENROUTER_API_KEY} - - JWT_SECRET=${JWT_SECRET} - - APP_URL=${APP_URL:-http://localhost} - - APP_NAME=${APP_NAME:-All You Can GET AI} - - CORS_ORIGINS=${CORS_ORIGINS:-http://localhost:12016} - volumes: - - ./data:/app/data - networks: - - app-network - healthcheck: - test: [ "CMD", "curl", "-f", "http://localhost:12015/health" ] - interval: 30s - timeout: 10s - retries: 3 - start_period: 5s - - frontend: - build: - context: ./frontend - dockerfile: Dockerfile - container_name: ai-frontend - ports: - - "12016:12016" - environment: - - FLASK_SECRET_KEY=${FLASK_SECRET_KEY} - - BACKEND_URL=${BACKEND_URL:-http://backend:12015} - 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 diff --git a/docs/7-deployment-view.md b/docs/7-deployment-view.md index 96d4d82..6c62bbc 100644 --- a/docs/7-deployment-view.md +++ b/docs/7-deployment-view.md @@ -39,68 +39,37 @@ Describes: ## Infrastructure Level 2 -### Docker Compose (Recommended for Development & Production) +### Coolify with Nixpacks (Production) -All services are containerized and orchestrated with `docker compose`: +Both services are deployed as separate Nixpacks resources in Coolify: ```text -┌─────────────────────────────────────────────────────────────┐ -│ Docker Host / VM │ -│ ┌──────────────────────────────────────────────────────┐ │ -│ │ Docker Network: app-network (bridge) │ │ -│ │ ┌──────────────────────────────────────────────┐ │ │ -│ │ │ Backend Container (FastAPI) │ │ │ -│ │ │ - Port: 12015 │ │ │ -│ │ │ - Service Name: backend │ │ │ -│ │ │ - Volume Mount: /app/data ← host/data/ │ │ │ -│ │ ├──────────────────────────────────────────────┤ │ │ -│ │ │ Frontend Container (Flask) │ │ │ -│ │ │ - Port: 12016 │ │ │ -│ │ │ - 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:12015 │ │ │ -│ │ │ / → frontend:12016 │ │ │ -│ │ └──────────────────────────────────────────────┘ │ │ -│ └──────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ Host Port Bindings │ -│ 80:80, 443:443, 12015:12015, 12016:12016 │ -└─────────────────────────────────────────────────────────────┘ - │ - Users / Internet +┌──────────────────────────────────────────────────────────┐ +│ Coolify Server │ +│ ┌────────────────────────────┐ │ +│ │ Backend Service (FastAPI) │ │ +│ │ - Base Dir: /backend │ │ +│ │ - Port: 12015 │ │ +│ │ - Volume: /app/data │ │ +│ ├────────────────────────────┤ │ +│ │ Frontend Service (Flask) │ │ +│ │ - Base Dir: /frontend │ │ +│ │ - Port: 12016 (public) │ │ +│ │ - BACKEND_URL: :12015 │ │ +│ └────────────────────────────┘ │ +│ ▲ │ +│ Coolify reverse proxy (TLS termination) │ +└──────────────────────────────────────────────────────────┘ + │ + 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:12016` 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:12015, frontend:12016) -- **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. **Recommended Path**: Deploy `docker-compose.coolify.yml` as one Coolify Docker Compose resource -2. **Public Entry Point**: Route domain to `nginx` service on port 80; backend and frontend stay internal -3. **Data Persistence**: Named volume keeps DuckDB data at `/app/data` -4. **Fallback Path**: Use separate Nixpacks services only when one-stack Compose deploy is not suitable - -**Note**: In Compose-based Coolify deployment, frontend reaches backend through Docker DNS at `http://backend:12015`. In Nixpacks-based deployment, use Coolify internal networking or colocate both services. +1. Create backend Nixpacks service in Coolify with Base Directory `/backend` +2. Create frontend Nixpacks service with Base Directory `/frontend` +3. Set environment variables per service +4. Attach domain to frontend on port `12016` +5. Enable Auto HTTPS in Coolify **See**: [Coolify Deployment Guide](./deployment/coolify.md) for detailed instructions. diff --git a/docs/deployment/coolify.md b/docs/deployment/coolify.md index df3a2ef..76d9aba 100644 --- a/docs/deployment/coolify.md +++ b/docs/deployment/coolify.md @@ -1,30 +1,6 @@ # Coolify Deployment Guide -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**: Coolify deployments, local development, consistent environments -- **Compose file**: `docker-compose.coolify.yml` in Coolify, `docker-compose.yml` locally -- **Key benefits**: - - Same containerized services 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 both Coolify paths. Use **Option 1 (Docker Compose)** for new deployments. Use **Option 2 (Nixpacks)** only if you need separate Coolify services instead of one stack. +This guide covers deploying `ai.allucanget.biz` using [Coolify](https://coolify.io) with Nixpacks from the repository `https://git.allucanget.biz/allucanget/ai.allucanget.biz.git`. ## Architecture Overview @@ -46,55 +22,6 @@ Coolify's built-in reverse proxy routes traffic: - Git repository pushed to `https://git.allucanget.biz/allucanget/ai.allucanget.biz.git` - Domain configured to point to your Coolify server -## Option 1: Deploy with Docker Compose in Coolify - -Use Coolify's **Docker Compose** resource with the dedicated compose file `docker-compose.coolify.yml`. - -### Step 1: Create Docker Compose Resource - -1. In Coolify, click **Add Resource** → **Deploy a new resource** → **Docker Compose** -2. Connect your Git repository (`git.allucanget.biz`) -3. Select the `ai.allucanget.biz` repository and `main` branch -4. Set **Compose File** to `docker-compose.coolify.yml` -5. Set **Base Directory** to `/` -6. Select the `frontend` service as the public-facing service on port `12016` -7. Click **Create Resource** - -### Step 2: Configure Environment Variables - -Add these in Coolify before first deploy: - -| Variable | Service | Example | -| -------------------- | ---------- | --------------------------- | -| `OPENROUTER_API_KEY` | `backend` | `sk-or-v1-...` | -| `JWT_SECRET` | `backend` | `openssl rand -hex 32` | -| `APP_URL` | `backend` | `https://ai.allucanget.biz` | -| `APP_NAME` | `backend` | `All You Can GET AI` | -| `CORS_ORIGINS` | `backend` | `https://ai.allucanget.biz` | -| `FLASK_SECRET_KEY` | `frontend` | `openssl rand -hex 32` | -| `BACKEND_URL` | `frontend` | `http://backend:12015` | - -### Step 3: Configure Domain and Proxy - -1. Attach domain `ai.allucanget.biz` to the `frontend` service on port `12016` -2. Enable **Auto HTTPS** in Coolify -3. Coolify terminates TLS and forwards traffic directly to `frontend:12016` - -No nginx service is needed in the Coolify stack. The frontend Flask app proxies `/api/*` calls to `http://backend:12015` internally. Coolify's own reverse proxy handles external TLS termination. - -### Step 4: Persistent Storage - -`docker-compose.coolify.yml` uses named volume `app-data` for DuckDB persistence at `/app/data`. No extra host bind mount needed for default setup. - -### Step 5: Deploy and Verify - -1. Start deployment in Coolify -2. Confirm `backend` becomes healthy -3. Open `https://ai.allucanget.biz/health` or proxied health route configured in Coolify -4. Open main domain and verify frontend loads - -## Option 2: Deploy with Nixpacks in Coolify - ## Step 1: Create Backend Service 1. In Coolify, click **Add Resource** → **Deploy a new resource** → **Git** @@ -142,6 +69,156 @@ Add these as **Runtime** environment variables in Coolify: 8. Click **Create Resource** +> **Note:** Nixpacks will automatically detect and install only the production dependencies from `requirements.txt`. +> **Important:** Nixpacks copies the **contents** of the Base Directory to `/app/` in the container. When Base Directory is `/frontend`, the `frontend/` folder wrapper is removed — only `app/`, `tests/`, and `requirements.txt` are copied. Therefore the start command uses `app.main:app` (not `frontend.app.main:app`). + +### Frontend Environment Variables + +Add these as **Runtime** environment variables in Coolify: + +| Variable | Description | Example | +| ------------------ | ----------------------------------------- | --------------------------------------------------------------- | +| `FLASK_SECRET_KEY` | Flask session cookie signing key | Generate with `openssl rand -hex 32` | +| `BACKEND_URL` | Internal URL to reach the backend service | `http://localhost:12015` (or use Coolify's internal networking) | + +## Step 3: Configure Reverse Proxy + +Coolify provides a built-in reverse proxy. Configure routing rules: + +### Backend Proxy Rules + +- **Domain**: `api.ai.allucanget.biz` (or subdomain of your choice) +- **Port**: `12015` +- **Path**: `/api/*` → forward to backend + +### Frontend Proxy Rules + +- **Domain**: `ai.allucanget.biz` +- **Port**: `12016` +- **Path**: `/` → forward to frontend + +## Step 4: SSL/TLS + +Enable HTTPS in Coolify for both services: + +1. Go to each service's settings +2. Enable **Auto HTTPS** (Let's Encrypt) +3. Configure domain names +4. Coolify automatically handles certificate renewal + +## Step 5: Persistent Storage (Optional) + +If you want to persist DuckDB data: + +1. In Coolify, go to the **Backend** service +2. Navigate to **Persistent Storage** +3. Add a volume mount: + - **Host Path**: `/data` (or any path on the host) + - **Container Path**: `/app/data` + - **Type**: `Bind Mount` or `Volume` + +## Troubleshooting + +### Backend healthcheck stays unhealthy + +- Check backend logs in Coolify +- Verify `OPENROUTER_API_KEY` and `JWT_SECRET` are set +- Verify volume mount at `/app/data` is writable + +### Backend won't start + +- Check that `OPENROUTER_API_KEY` is set +- Verify `JWT_SECRET` is a sufficiently long random string +- Check logs in Coolify's **Logs** tab + +### Frontend can't reach backend + +- Ensure `BACKEND_URL` points to the correct internal URL +- If both services are on the same Coolify server, use `http://localhost:12015` +- Check that the backend service is running and healthy + +### CORS errors + +- Set `CORS_ORIGINS` to include your frontend domain +- Example: `https://ai.allucanget.biz` + +### Nixpacks build fails + +- Verify the base directory is correct (`/backend` or `/frontend`) +- Check that `requirements.txt` exists in the base directory +- Review build logs in Coolify + +## Environment Variable Summary + +All required environment variables: + +| Variable | Service | Required | +| -------------------- | -------- | ------------------------------------- | +| `OPENROUTER_API_KEY` | Backend | Yes | +| `JWT_SECRET` | Backend | Yes | +| `APP_URL` | Backend | Yes | +| `APP_NAME` | Backend | No (defaults to "All You Can GET AI") | +| `CORS_ORIGINS` | Backend | Yes | +| `FLASK_SECRET_KEY` | Frontend | Yes | +| `BACKEND_URL` | Frontend | Yes | + +## Deployment Checklist + +- [ ] Repository pushed to Git +- [ ] Backend service created with correct base directory (`/backend`) +- [ ] Backend environment variables configured +- [ ] Frontend service created with correct base directory (`/frontend`) +- [ ] Frontend environment variables configured +- [ ] SSL certificates enabled +- [ ] Domain names configured +- [ ] Health checks passing +- [ ] Logs reviewed for errors + +1. In Coolify, click **Add Resource** → **Deploy a new resource** → **Git** +2. Connect your Git repository (`git.allucanget.biz`) +3. Select the `ai.allucanget.biz` repository +4. Choose the `main` branch +5. Set **Build Pack** to `nixpacks` +6. **CRITICAL: Set Base Directory to `/backend`** — this tells Nixpacks to look in the `backend/` subdirectory for `requirements.txt` and the Python application +7. Set **Ports Exposed** to `12015` +8. Set **Start Command** to: + + ```txt + uvicorn app.main:app --host 0.0.0.0 --port 12015 + ``` + +9. Click **Create Resource** + +> **Important:** Nixpacks copies the **contents** of the Base Directory to `/app/` in the container. When Base Directory is `/backend`, the `backend/` folder wrapper is removed — only `app/`, `tests/`, and `requirements.txt` are copied. Therefore the start command uses `app.main:app` (not `backend.app.main:app`). + +### Backend Environment Variables + +Add these as **Runtime** environment variables in Coolify: + +| Variable | Description | Example | +| -------------------- | ------------------------------------ | ------------------------------------ | +| `OPENROUTER_API_KEY` | OpenRouter API key for AI generation | `sk-or-v1-...` | +| `JWT_SECRET` | Secret key for JWT token signing | Generate with `openssl rand -hex 32` | +| `APP_URL` | Public URL of the backend | `https://api.ai.allucanget.biz` | +| `APP_NAME` | Application name | `All You Can GET AI` | +| `CORS_ORIGINS` | Comma-separated allowed origins | `https://ai.allucanget.biz` | + +## Step 2: Create Frontend Service + +1. In Coolify, click **Add Resource** → **Deploy a new resource** → **Git** +2. Select the same repository +3. Choose the `main` branch +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 +6. Set **Ports Exposed** to `12016` +7. Set **Start Command** to: + + ```txt + gunicorn app.main:app --bind 0.0.0.0:12016 --workers 2 --timeout 120 + ``` + +8. Click **Create Resource** + > **Note:** The frontend uses `requirements.txt` for production dependencies and `requirements-dev.txt` for development dependencies (like pytest). Nixpacks will automatically detect and install only the production dependencies. > **Important:** Nixpacks copies the **contents** of the Base Directory to `/app/` in the container. When Base Directory is `/frontend`, the `frontend/` folder wrapper is removed — only `app/`, `tests/`, and `requirements.txt` are copied. Therefore the start command uses `app.main:app` (not `frontend.app.main:app`). diff --git a/docs/deployment/docker-compose.md b/docs/deployment/docker-compose.md deleted file mode 100644 index bc86126..0000000 --- a/docs/deployment/docker-compose.md +++ /dev/null @@ -1,243 +0,0 @@ -# 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:12016 - - Backend API: http://localhost:12015 - - API Health: http://localhost:12015/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:12015` (Docker) or `http://localhost:12015` (local dev) | -| `CORS_ORIGINS` | Allowed CORS origins for backend | `http://localhost:12016` (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 | `All You Can GET AI` | - -### 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 12016 │ │ Port 12015 │ │ -│ │ 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:12015->12015/tcp -ai-frontend "gunicorn app.main:…" frontend Up 2m 0.0.0.0:12016->12016/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 12015 or 12016 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:12015" # Maps host:13000 to container:12015 - - "13001:12016" # Maps host:13001 to container:12016 -``` - -### 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:12015` (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/) diff --git a/nginx/docker-compose.conf b/nginx/docker-compose.conf deleted file mode 100644 index eef99ac..0000000 --- a/nginx/docker-compose.conf +++ /dev/null @@ -1,53 +0,0 @@ -# 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:12015; -} - -# Frontend proxy - use Docker service name instead of localhost -upstream frontend { - server frontend:12016; -} - -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; - } -}