# Stirling-PDF Unified Container

Single Docker container that can run as **frontend + backend**, **frontend only**, or **backend only** using the `MODE` environment variable.

## Quick Start

### MODE=BOTH (Default)
Single container with both frontend and backend on port 8080:

```bash
docker run -p 8080:8080 \
  -e MODE=BOTH \
  stirlingtools/stirling-pdf:unified
```

Access at: `http://localhost:8080`

### MODE=FRONTEND
Frontend only, connecting to separate backend:

```bash
docker run -p 8080:8080 \
  -e MODE=FRONTEND \
  -e VITE_API_BASE_URL=http://backend:8080 \
  stirlingtools/stirling-pdf:unified
```

### MODE=BACKEND
Backend API only:

```bash
docker run -p 8080:8080 \
  -e MODE=BACKEND \
  stirlingtools/stirling-pdf:unified
```

Access API at: `http://localhost:8080/api`
Swagger UI at: `http://localhost:8080/swagger-ui/index.html`

---

## Architecture

### MODE=BOTH (Default)
```
┌─────────────────────────────────────┐
│     Port 8080 (External)            │
│  ┌───────────────────────────────┐  │
│  │         Nginx                 │  │
│  │  • Serves frontend (/)        │  │
│  │  • Proxies /api/* → backend   │  │
│  └───────────┬───────────────────┘  │
│              │                       │
│  ┌───────────▼───────────────────┐  │
│  │    Backend (Internal 8081)    │  │
│  │  • Spring Boot                │  │
│  │  • PDF Processing             │  │
│  │  • UnoServer                  │  │
│  └───────────────────────────────┘  │
└─────────────────────────────────────┘
```

### MODE=FRONTEND
```
┌─────────────────────────────┐      ┌──────────────────┐
│   Frontend Container        │      │  Backend         │
│   Port 8080                 │      │  (External)      │
│  ┌───────────────────────┐  │      │                  │
│  │       Nginx           │  │──────▶  :8080/api       │
│  │  • Serves frontend    │  │      │                  │
│  │  • Proxies to backend │  │      │                  │
│  └───────────────────────┘  │      └──────────────────┘
└─────────────────────────────┘
```

### MODE=BACKEND
```
┌─────────────────────────────┐
│   Backend Container         │
│   Port 8080                 │
│  ┌───────────────────────┐  │
│  │   Spring Boot         │  │
│  │  • API Endpoints      │  │
│  │  • PDF Processing     │  │
│  │  • UnoServer          │  │
│  └───────────────────────┘  │
└─────────────────────────────┘
```

---

## Environment Variables

### MODE Configuration

| Variable | Values | Default | Description |
|----------|--------|---------|-------------|
| `MODE` | `BOTH`, `FRONTEND`, `BACKEND` | `BOTH` | Container operation mode |

### MODE=BOTH Specific

| Variable | Default | Description |
|----------|---------|-------------|
| `BACKEND_INTERNAL_PORT` | `8081` | Internal port for backend when MODE=BOTH |

### MODE=FRONTEND Specific

| Variable | Default | Description |
|----------|---------|-------------|
| `VITE_API_BASE_URL` | `http://backend:8080` | Backend URL for API proxying |

### Standard Configuration

All modes support standard Stirling-PDF environment variables:

- `DISABLE_ADDITIONAL_FEATURES` - Enable/disable OCR and LibreOffice features
- `DOCKER_ENABLE_SECURITY` - Enable authentication
- `PUID` / `PGID` - User/Group IDs
- `SYSTEM_MAXFILESIZE` - Max upload size (MB)
- `TESSERACT_LANGS` - Comma-separated OCR language codes
- `JAVA_CUSTOM_OPTS` - Additional JVM options

See full configuration docs at: https://docs.stirlingpdf.com

---

## Docker Compose Examples

### Example 1: All-in-One (MODE=BOTH)

**File:** `docker/compose/docker-compose-unified-both.yml`

```yaml
services:
  stirling-pdf:
    image: stirlingtools/stirling-pdf:unified
    ports:
      - "8080:8080"
    volumes:
      - ./data:/usr/share/tessdata:rw
      - ./config:/configs:rw
    environment:
      MODE: BOTH
    restart: unless-stopped
```

### Example 2: Separate Frontend & Backend

**File:** `docker/compose/docker-compose-unified-frontend.yml`

```yaml
services:
  backend:
    image: stirlingtools/stirling-pdf:unified
    ports:
      - "8081:8080"
    environment:
      MODE: BACKEND
    volumes:
      - ./data:/usr/share/tessdata:rw
      - ./config:/configs:rw

  frontend:
    image: stirlingtools/stirling-pdf:unified
    ports:
      - "8080:8080"
    environment:
      MODE: FRONTEND
      VITE_API_BASE_URL: http://backend:8080
    depends_on:
      - backend
```

### Example 3: Backend API Only

**File:** `docker/compose/docker-compose-unified-backend.yml`

```yaml
services:
  stirling-pdf-api:
    image: stirlingtools/stirling-pdf:unified
    ports:
      - "8080:8080"
    environment:
      MODE: BACKEND
    volumes:
      - ./data:/usr/share/tessdata:rw
      - ./config:/configs:rw
    restart: unless-stopped
```

---

## Building the Image

```bash
# From repository root
docker build -t stirlingtools/stirling-pdf:unified -f docker/Dockerfile.unified .
```

### Build Arguments

| Argument | Description |
|----------|-------------|
| `VERSION_TAG` | Version tag for the image |

Example:
```bash
docker build \
  --build-arg VERSION_TAG=v1.0.0 \
  -t stirlingtools/stirling-pdf:unified \
  -f docker/Dockerfile.unified .
```

---

## Use Cases

### 1. Simple Deployment (MODE=BOTH)
- **Best for:** Personal use, small teams, simple deployments
- **Pros:** Single container, easy setup, minimal configuration
- **Cons:** Frontend and backend scale together

### 2. Scaled Frontend (MODE=FRONTEND + BACKEND)
- **Best for:** High traffic, need to scale frontend independently
- **Pros:** Scale frontend containers separately, CDN-friendly
- **Example:**
  ```yaml
  services:
    backend:
      image: stirlingtools/stirling-pdf:unified
      environment:
        MODE: BACKEND
      deploy:
        replicas: 1

    frontend:
      image: stirlingtools/stirling-pdf:unified
      environment:
        MODE: FRONTEND
        VITE_API_BASE_URL: http://backend:8080
      deploy:
        replicas: 5  # Scale frontend independently
  ```

### 3. API-Only (MODE=BACKEND)
- **Best for:** Headless deployments, custom frontends, API integrations
- **Pros:** Minimal resources, no nginx overhead
- **Example:** Use with external frontend or API consumers

### 4. Multi-Backend Setup
- **Best for:** Load balancing, high availability
- **Example:**
  ```yaml
  services:
    backend-1:
      image: stirlingtools/stirling-pdf:unified
      environment:
        MODE: BACKEND

    backend-2:
      image: stirlingtools/stirling-pdf:unified
      environment:
        MODE: BACKEND

    frontend:
      image: stirlingtools/stirling-pdf:unified
      environment:
        MODE: FRONTEND
        VITE_API_BASE_URL: http://load-balancer:8080
  ```

---

## Port Configuration

All modes use **port 8080** by default:

- **MODE=BOTH**: Nginx listens on 8080, proxies to backend on internal 8081
- **MODE=FRONTEND**: Nginx listens on 8080
- **MODE=BACKEND**: Spring Boot listens on 8080

**Expose port 8080** in all configurations:
```yaml
ports:
  - "8080:8080"
```

---

## Health Checks

### MODE=BOTH and MODE=BACKEND
```yaml
healthcheck:
  test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status || exit 1"]
  interval: 30s
  timeout: 10s
  retries: 3
```

### MODE=FRONTEND
```yaml
healthcheck:
  test: ["CMD-SHELL", "curl -f http://localhost:8080/ || exit 1"]
  interval: 30s
  timeout: 10s
  retries: 3
```

---

## Troubleshooting

### Check logs
```bash
docker logs stirling-pdf-container
```

Look for the startup banner:
```
===================================
Stirling-PDF Unified Container
MODE: BOTH
===================================
```

### Invalid MODE error
```
ERROR: Invalid MODE 'XYZ'. Must be BOTH, FRONTEND, or BACKEND
```
**Fix:** Set `MODE` to one of the three valid values.

### Frontend can't connect to backend (MODE=FRONTEND)
**Check:**
1. `VITE_API_BASE_URL` points to correct backend URL
2. Backend container is running and accessible
3. Network connectivity between containers

### Backend not starting (MODE=BOTH or BACKEND)
**Check:**
1. Sufficient memory allocated (4GB recommended)
2. Java heap size (`JAVA_CUSTOM_OPTS`)
3. Volume permissions for `/tmp/stirling-pdf`

---

## Migration Guide

### From Separate Containers → MODE=BOTH

**Before:**
```yaml
services:
  frontend:
    image: stirlingtools/stirling-pdf:frontend
    ports: ["80:80"]

  backend:
    image: stirlingtools/stirling-pdf:backend
    ports: ["8080:8080"]
```

**After:**
```yaml
services:
  stirling-pdf:
    image: stirlingtools/stirling-pdf:unified
    ports: ["8080:8080"]
    environment:
      MODE: BOTH
```

### From Legacy → MODE=BACKEND
```yaml
services:
  stirling-pdf:
    image: stirlingtools/stirling-pdf:latest
    ports: ["8080:8080"]
```

**Becomes:**
```yaml
services:
  stirling-pdf:
    image: stirlingtools/stirling-pdf:unified
    ports: ["8080:8080"]
    environment:
      MODE: BACKEND
```

---

## Performance Tuning

### MODE=BOTH
```yaml
environment:
  JAVA_CUSTOM_OPTS: "-Xmx4g -XX:MaxRAMPercentage=75"
  BACKEND_INTERNAL_PORT: 8081
deploy:
  resources:
    limits:
      memory: 4G
    reservations:
      memory: 2G
```

### MODE=FRONTEND (Lightweight)
```yaml
deploy:
  resources:
    limits:
      memory: 512M
    reservations:
      memory: 256M
```

### MODE=BACKEND (Heavy Processing)
```yaml
environment:
  JAVA_CUSTOM_OPTS: "-Xmx8g"
deploy:
  resources:
    limits:
      memory: 10G
    reservations:
      memory: 4G
```

---

## Security Considerations

1. **MODE=BOTH**: Backend not exposed externally (runs on internal port)
2. **MODE=BACKEND**: API exposed directly - consider API authentication
3. **MODE=FRONTEND**: Only serves static files - minimal attack surface

Enable security features:
```yaml
environment:
  DOCKER_ENABLE_SECURITY: "true"
  SECURITY_ENABLELOGIN: "true"
```

---

## Support

- Documentation: https://docs.stirlingpdf.com
- GitHub Issues: https://github.com/Stirling-Tools/Stirling-PDF/issues
- Docker Hub: https://hub.docker.com/r/stirlingtools/stirling-pdf

---

## License

MIT License - See repository for full details
