# Docker Setup

Containerized deployment for production or quick testing.

## Prerequisites

- Docker 24+ and Docker Compose 2.20+
- Git 2.x

See [Prerequisites](1-prerequisites.md) for installation instructions.

## Step 1: Clone Repository

```bash
git clone https://git.mosaicstack.dev/mosaic/stack mosaic-stack
cd mosaic-stack
```

## Step 2: Configure Environment

```bash
cp .env.example .env
nano .env  # Configure as needed
```

**Key variables for Docker deployment:**

```bash
# Database (Docker internal networking)
DATABASE_URL=postgresql://mosaic:mosaic_dev_password@postgres:5432/mosaic
POSTGRES_USER=mosaic
POSTGRES_PASSWORD=mosaic_dev_password
POSTGRES_DB=mosaic

# Valkey (Docker internal networking)
VALKEY_URL=redis://valkey:6379

# Application URLs
NEXT_PUBLIC_API_URL=http://localhost:3001

# JWT
JWT_SECRET=$(openssl rand -base64 32)
JWT_EXPIRATION=24h
```

## Step 3: Start Services

### Option A: Core Services Only (Recommended for Development)

Start PostgreSQL, Valkey, API, and Web:

```bash
# Start core stack
docker compose up -d

# View startup logs
docker compose logs -f

# Check service status
docker compose ps
```

### Option B: With Optional Services

Enable Authentik OIDC and/or Ollama AI:

```bash
# With Authentik only
docker compose --profile authentik up -d

# With Ollama only
docker compose --profile ollama up -d

# With all optional services
docker compose --profile full up -d

# Or set in .env file
echo "COMPOSE_PROFILES=full" >> .env
docker compose up -d
```

**Services available:**

| Service              | Container                 | Port       | Profile   | Purpose                |
| -------------------- | ------------------------- | ---------- | --------- | ---------------------- |
| PostgreSQL           | mosaic-postgres           | 5432       | core      | Database with pgvector |
| Valkey               | mosaic-valkey             | 6379       | core      | Redis-compatible cache |
| API                  | mosaic-api                | 3001       | core      | NestJS backend         |
| Web                  | mosaic-web                | 3000       | core      | Next.js frontend       |
| Authentik Server     | mosaic-authentik-server   | 9000, 9443 | authentik | OIDC provider          |
| Authentik Worker     | mosaic-authentik-worker   | -          | authentik | Background jobs        |
| Authentik PostgreSQL | mosaic-authentik-postgres | -          | authentik | Auth database          |
| Authentik Redis      | mosaic-authentik-redis    | -          | authentik | Auth cache             |
| Ollama               | mosaic-ollama             | 11434      | ollama    | LLM service            |

## Step 4: Run Database Migrations

```bash
# Enter API container
docker compose exec api sh

# Run migrations
pnpm prisma migrate deploy

# Seed development data (optional)
pnpm prisma:seed

# Exit container
exit
```

## Step 5: Verify Deployment

### Check API Health

```bash
curl http://localhost:3001/health
```

### View Logs

```bash
# All services
docker compose logs -f

# Specific service
docker compose logs -f api

# Last 100 lines
docker compose logs --tail=100 api
```

### Access Containers

```bash
# API container shell
docker compose exec api sh

# PostgreSQL client
docker compose exec postgres psql -U mosaic -d mosaic

# Redis CLI
docker compose exec valkey redis-cli
```

## Management Commands

### Start/Stop Services

```bash
# Start all
docker compose up -d

# Stop all
docker compose stop

# Stop and remove containers
docker compose down

# Stop and remove containers + volumes (WARNING: deletes data)
docker compose down -v
```

### Restart Services

```bash
# Restart all
docker compose restart

# Restart specific service
docker compose restart api
```

### View Service Status

```bash
# List running containers
docker compose ps

# View resource usage
docker stats

# View logs
docker compose logs -f [service_name]
```

### Rebuild After Code Changes

```bash
# Rebuild and restart
docker compose up -d --build

# Rebuild specific service
docker compose build api
docker compose up -d api
```

## Production Deployment

### Environment Configuration

Create a production `.env` file:

```bash
# Production database
DATABASE_URL=postgresql://user:pass@prod-db-host:5432/mosaic

# Production Redis
REDIS_URL=redis://prod-redis-host:6379

# Production URLs
NEXT_PUBLIC_APP_URL=https://mosaic.example.com

# Secure JWT secret
JWT_SECRET=$(openssl rand -base64 64)
JWT_EXPIRATION=24h

# Authentik OIDC
OIDC_ISSUER=https://auth.example.com/application/o/mosaic/
OIDC_CLIENT_ID=prod-client-id
OIDC_CLIENT_SECRET=prod-client-secret
OIDC_REDIRECT_URI=https://mosaic.example.com/auth/oauth2/callback/authentik
```

### Compose Override for Production

Create `docker-compose.prod.yml`:

```yaml
services:
  api:
    restart: always
    environment:
      NODE_ENV: production
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: "1.0"
          memory: 1G

  web:
    restart: always
    environment:
      NODE_ENV: production
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: "0.5"
          memory: 512M
```

**Deploy:**

```bash
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
```

## Troubleshooting

### Containers Won't Start

```bash
# Check logs for errors
docker compose logs api
docker compose logs postgres

# Check container status
docker compose ps

# Restart specific service
docker compose restart api
```

### Database Connection Failed

```bash
# Check PostgreSQL is running
docker compose ps postgres

# Check PostgreSQL logs
docker compose logs postgres

# Test connection from API container
docker compose exec api sh
nc -zv postgres 5432
```

### Port Already in Use

```bash
# Find what's using the port
lsof -i :3001

# Kill the process or change port in docker-compose.yml
```

### Out of Disk Space

```bash
# Remove unused containers/images
docker system prune -a

# Remove unused volumes (WARNING: may delete data)
docker volume prune
```

### Permission Errors

```bash
# Add user to docker group
sudo usermod -aG docker $USER

# Log out and back in, or
newgrp docker
```

## Monitoring

### Resource Usage

```bash
# Live resource stats
docker stats

# Container logs
docker compose logs -f --tail=100
```

### Health Checks

```bash
# API health endpoint
curl http://localhost:3001/health

# PostgreSQL connection
docker compose exec postgres pg_isready -U mosaic

# Redis ping
docker compose exec valkey redis-cli ping
```

## Updating

### Pull Latest Changes

```bash
git pull origin develop

# Rebuild and restart
docker compose up -d --build
```

### Update Docker Images

```bash
# Pull latest base images
docker compose pull

# Rebuild
docker compose up -d --build
```

## Backup and Restore

### Database Backup

```bash
# Backup database
docker compose exec postgres pg_dump -U mosaic -d mosaic > backup-$(date +%Y%m%d).sql

# Restore database
cat backup-20260128.sql | docker compose exec -T postgres psql -U mosaic -d mosaic
```

### Volume Backup

```bash
# Backup PostgreSQL volume
docker run --rm \
  -v mosaic-stack_postgres-data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/postgres-backup.tar.gz /data
```

## Next Steps

1. **Configure Authentication** — [Authentik Setup](../3-configuration/2-authentik.md)
2. **Monitor Logs** — Set up log aggregation for production
3. **Set up Backups** — Automate database backups
4. **Configure SSL** — Add reverse proxy (Traefik/Nginx) for HTTPS
