# 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 | `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 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/)