# Docker Setup Documentation

## Overview

This document describes the production-ready Docker setup for the Feuerwehr Dashboard application, including multi-stage builds, security best practices, and deployment instructions.

## Architecture

The application consists of three Docker containers:

1. **PostgreSQL Database** - postgres:16-alpine
2. **Backend API** - Node.js application (TypeScript compiled to JavaScript)
3. **Frontend** - React SPA served by Nginx

All containers are connected via a Docker bridge network and orchestrated using Docker Compose.

## Files Structure

```
feuerwehr_dashboard/
├── docker-compose.yml          # Production orchestration
├── docker-compose.dev.yml      # Development orchestration
├── docker-test.sh              # Docker build testing script
├── backend/
│   ├── Dockerfile              # Multi-stage backend build
│   └── .dockerignore           # Backend Docker ignore rules
└── frontend/
    ├── Dockerfile              # Multi-stage frontend build
    ├── nginx.conf              # Nginx configuration for SPA
    └── .dockerignore           # Frontend Docker ignore rules
```

## Backend Dockerfile

**Location:** `/backend/Dockerfile`

### Features

- **Multi-stage build** - Separate build and production stages
- **Build stage:**
  - Based on node:20-alpine
  - Installs all dependencies (including devDependencies)
  - Compiles TypeScript to JavaScript
  - Prunes devDependencies after build
- **Production stage:**
  - Based on node:20-alpine
  - Installs wget for health checks
  - Creates non-root user (nodejs:1001)
  - Copies only production node_modules
  - Copies compiled JavaScript
  - Copies database migrations to dist/
  - Runs as non-root user
  - Exposes port 3000
  - Includes health check

### Build Command

```bash
cd backend
docker build -t feuerwehr-backend:latest .
```

### Image Size

Expected final image size: ~150-200 MB (alpine-based)

### Security Features

- Non-root user execution
- Minimal base image (Alpine Linux)
- Only production dependencies included
- No source code in final image

## Frontend Dockerfile

**Location:** `/frontend/Dockerfile`

### Features

- **Multi-stage build** - Build stage with Node.js + production stage with Nginx
- **Build stage:**
  - Based on node:20-alpine
  - Installs dependencies
  - Runs Vite build
  - Accepts build arguments for environment variables
- **Production stage:**
  - Based on nginx:alpine
  - Installs wget for health checks
  - Copies custom nginx.conf
  - Copies built static assets
  - Configures non-root nginx user
  - Exposes port 80
  - Includes health check

### Build Command

```bash
cd frontend
docker build \
  --build-arg VITE_API_URL=http://localhost:3000 \
  --build-arg VITE_APP_NAME="Feuerwehr Dashboard" \
  --build-arg VITE_APP_VERSION="1.0.0" \
  -t feuerwehr-frontend:latest .
```

### Build Arguments

- `VITE_API_URL` - Backend API URL (default: http://localhost:3000)
- `VITE_APP_NAME` - Application name (default: "Feuerwehr Dashboard")
- `VITE_APP_VERSION` - Application version (default: "1.0.0")

### Image Size

Expected final image size: ~50-80 MB (alpine + static assets)

### Security Features

- Non-root nginx execution
- Minimal base image (Alpine Linux)
- Security headers configured
- No source code in final image

## Nginx Configuration

**Location:** `/frontend/nginx.conf`

### Features

1. **SPA Routing**
   - All routes fall back to index.html
   - Proper handling of client-side routing

2. **Performance**
   - Gzip compression enabled
   - Static asset caching (1 year)
   - No caching for index.html

3. **Security Headers**
   - X-Frame-Options: SAMEORIGIN
   - X-Content-Type-Options: nosniff
   - X-XSS-Protection: 1; mode=block
   - Referrer-Policy: strict-origin-when-cross-origin

4. **Health Check**
   - Endpoint: /health
   - Returns 200 with "healthy" text

5. **Error Handling**
   - 404 errors redirect to index.html
   - Custom 50x error page

## Docker Compose

**Location:** `/docker-compose.yml`

### Services

#### PostgreSQL

```yaml
postgres:
  image: postgres:16-alpine
  ports: 5432:5432
  volumes: postgres_data_prod
  health_check: pg_isready
  restart: unless-stopped
```

#### Backend

```yaml
backend:
  build: ./backend
  ports: 3000:3000
  depends_on: postgres (healthy)
  health_check: wget localhost:3000/health
  restart: unless-stopped
```

#### Frontend

```yaml
frontend:
  build: ./frontend
  build_args: VITE_API_URL
  ports: 80:80
  depends_on: backend (healthy)
  health_check: wget localhost:80/health
  restart: unless-stopped
```

### Environment Variables

Create a `.env` file based on `.env.example`:

**Required:**
- `POSTGRES_PASSWORD` - Database password
- `JWT_SECRET` - JWT signing secret

**Optional:**
- `POSTGRES_DB` - Database name (default: feuerwehr_prod)
- `POSTGRES_USER` - Database user (default: prod_user)
- `POSTGRES_PORT` - Database port (default: 5432)
- `BACKEND_PORT` - Backend port (default: 3000)
- `FRONTEND_PORT` - Frontend port (default: 80)
- `CORS_ORIGIN` - CORS origin (default: http://localhost:80)
- `VITE_API_URL` - Frontend API URL (default: http://localhost:3000)

### Networks

- `feuerwehr_network` - Bridge network connecting all services

### Volumes

- `postgres_data_prod` - Persistent PostgreSQL data

## Usage

### 1. Test Docker Builds

Run the test script to verify Docker builds work:

```bash
./docker-test.sh
```

This script will:
- Check Docker availability
- Build backend image
- Build frontend image
- Report success/failure
- Optionally cleanup test images

### 2. Configure Environment

Copy and configure environment file:

```bash
cp .env.example .env
# Edit .env and set required variables
```

### 3. Build and Start Services

```bash
# Build and start all services
docker-compose up -d

# View logs
docker-compose logs -f

# Check service status
docker-compose ps
```

### 4. Access Application

- **Frontend:** http://localhost:80
- **Backend API:** http://localhost:3000
- **Database:** localhost:5432

### 5. Stop Services

```bash
# Stop all services
docker-compose down

# Stop and remove volumes
docker-compose down -v
```

## Health Checks

All services include health checks:

### PostgreSQL
- **Command:** `pg_isready -U $USER -d $DB`
- **Interval:** 10s
- **Retries:** 5

### Backend
- **Command:** `wget localhost:3000/health`
- **Interval:** 30s
- **Retries:** 3
- **Start Period:** 40s

### Frontend
- **Command:** `wget localhost:80/health`
- **Interval:** 30s
- **Retries:** 3
- **Start Period:** 30s

## Troubleshooting

### Backend Build Fails

1. Check TypeScript compilation:
```bash
cd backend
npm install
npm run build
```

2. Verify all source files exist
3. Check tsconfig.json configuration

### Frontend Build Fails

1. Check Vite build:
```bash
cd frontend
npm install
npm run build
```

2. Verify all dependencies are installed
3. Check build arguments are correct

### Container Won't Start

1. Check logs:
```bash
docker-compose logs [service-name]
```

2. Verify environment variables in .env
3. Check health check status:
```bash
docker-compose ps
```

### Database Connection Issues

1. Verify DATABASE_URL format:
```
postgresql://user:password@postgres:5432/database
```

2. Check postgres service is healthy:
```bash
docker-compose ps postgres
```

3. Verify network connectivity:
```bash
docker-compose exec backend ping postgres
```

## Security Considerations

### Production Checklist

- [ ] Set strong POSTGRES_PASSWORD
- [ ] Set strong JWT_SECRET (min 32 characters)
- [ ] Use HTTPS in production
- [ ] Configure proper CORS_ORIGIN
- [ ] Enable firewall rules
- [ ] Regular security updates
- [ ] Monitor container logs
- [ ] Backup database regularly

### Image Security

- Alpine Linux base (minimal attack surface)
- Non-root user execution
- No unnecessary packages
- Security headers enabled
- Health checks configured

## Maintenance

### Update Dependencies

```bash
# Rebuild images with latest dependencies
docker-compose build --no-cache
docker-compose up -d
```

### Backup Database

```bash
# Create backup
docker-compose exec postgres pg_dump -U $USER $DB > backup.sql

# Restore backup
docker-compose exec -T postgres psql -U $USER $DB < backup.sql
```

### View Logs

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

# Specific service
docker-compose logs -f backend

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

### Restart Services

```bash
# Restart all
docker-compose restart

# Restart specific service
docker-compose restart backend
```

## Performance Optimization

### Build Cache

Docker uses layer caching. To optimize:

1. Copy package files first
2. Install dependencies
3. Copy source code last

This ensures dependency installation is cached.

### Image Size

Current image sizes:
- Backend: ~150-200 MB
- Frontend: ~50-80 MB
- Total: ~200-280 MB

### Resource Limits

Add resource limits in docker-compose.yml:

```yaml
services:
  backend:
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M
```

## Monitoring

### Container Stats

```bash
docker stats
```

### Health Status

```bash
docker-compose ps
```

### Resource Usage

```bash
docker system df
```

## Production Deployment

### Using Docker Compose

```bash
# On production server
git clone <repository>
cd feuerwehr_dashboard
cp .env.example .env
# Configure .env with production values
docker-compose up -d
```

### Using Container Registry

```bash
# Build and tag images
docker build -t registry.example.com/feuerwehr-backend:v1.0.0 backend/
docker build -t registry.example.com/feuerwehr-frontend:v1.0.0 frontend/

# Push to registry
docker push registry.example.com/feuerwehr-backend:v1.0.0
docker push registry.example.com/feuerwehr-frontend:v1.0.0

# Pull and run on production
docker pull registry.example.com/feuerwehr-backend:v1.0.0
docker pull registry.example.com/feuerwehr-frontend:v1.0.0
docker-compose up -d
```

## Additional Resources

- [Docker Documentation](https://docs.docker.com/)
- [Docker Compose Documentation](https://docs.docker.com/compose/)
- [Nginx Documentation](https://nginx.org/en/docs/)
- [Node.js Best Practices](https://github.com/goldbergyoni/nodebestpractices)
