Files
pastel-ui/DOCKER.md
valknarness 27ff7f7ffd feat: implement runtime configuration with API proxy pattern
Replace build-time NEXT_PUBLIC_* environment variables with server-side
runtime configuration. This allows changing the Pastel API URL without
rebuilding the Docker image.

**Changes:**
- Add Next.js API proxy route at /api/pastel/[...path] for server-side proxying
- Update API client to use proxy endpoint instead of direct API URL
- Replace NEXT_PUBLIC_API_URL with server-side PASTEL_API_URL
- Remove build arguments from Dockerfile (no longer needed)
- Simplify docker-compose.yml to use runtime environment variables only
- Update all .env files to reflect new configuration approach
- Add comprehensive DOCKER.md documentation

**Benefits:**
- No rebuild required to change API URL
- Same image works across all environments (dev/staging/prod)
- Better security (API URL not exposed in client bundle)
- Simpler deployment and configuration management

**Migration:**
Old: NEXT_PUBLIC_API_URL (build-time, embedded in bundle)
New: PASTEL_API_URL (runtime, read by server proxy)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 16:05:55 +01:00

5.8 KiB

Docker Deployment Guide

Runtime Configuration

This application uses a Next.js API proxy pattern to allow runtime configuration without rebuilding the Docker image.

How It Works

  1. Client makes requests to /api/pastel/*
  2. Next.js API Route (app/api/pastel/[...path]/route.ts) proxies requests to the backend
  3. Backend API URL is read from PASTEL_API_URL environment variable at runtime

This means you can change the backend API URL by simply restarting the container with a different environment variable - no rebuild required!

Quick Start

Using Docker Compose

# Start both UI and API
docker-compose up -d

# The UI will automatically connect to the API container
# (configured via PASTEL_API_URL=http://pastel-api:3001)

Using Docker Run

# Build the image once
docker build -t pastel-ui .

# Run with default settings (expects API at http://localhost:3001)
docker run -p 3000:3000 pastel-ui

# Run with custom API URL (no rebuild needed!)
docker run -p 3000:3000 \
  -e PASTEL_API_URL=http://my-api-server:3001 \
  pastel-ui

# Run with external API
docker run -p 3000:3000 \
  -e PASTEL_API_URL=https://api.example.com \
  pastel-ui

Environment Variables

Server-Side (Runtime Configuration)

Variable Description Default Example
PASTEL_API_URL Backend API URL http://localhost:3001 http://pastel-api:3001
NODE_ENV Node environment production production
PORT Server port 3000 3000

Important: These can be changed at runtime without rebuilding the image!

Configuration Examples

Docker Compose with Custom API

# docker-compose.yml
services:
  pastel-ui:
    image: ghcr.io/valknarness/pastel-ui:latest
    ports:
      - "3000:3000"
    environment:
      - PASTEL_API_URL=http://my-custom-api:8080

Docker Compose with External API

services:
  pastel-ui:
    image: ghcr.io/valknarness/pastel-ui:latest
    ports:
      - "3000:3000"
    environment:
      - PASTEL_API_URL=https://api.pastel.example.com

Using .env File

# .env
PASTEL_API_URL=http://pastel-api:3001

# docker-compose.yml will automatically read this
docker-compose up -d

Local Development

# Install dependencies
pnpm install

# Create .env.local file
cat > .env.local << EOF
PASTEL_API_URL=http://localhost:3001
EOF

# Start development server
pnpm dev

# Open http://localhost:3000

Building

# Build the Docker image
docker build -t pastel-ui .

# No build arguments needed - configuration is runtime!

Health Checks

The container includes health checks using curl:

# Check container health
docker inspect --format='{{.State.Health.Status}}' pastel-ui

# Manual health check
curl http://localhost:3000/

Troubleshooting

API Connection Issues

Problem: Cannot connect to Pastel API

Solutions:

  1. Check API URL:

    docker exec pastel-ui env | grep PASTEL_API_URL
    
  2. Test API connectivity from container:

    docker exec pastel-ui curl -f ${PASTEL_API_URL}/api/v1/health
    
  3. Check Docker network:

    docker network inspect pastel-network
    
  4. Update API URL without rebuild:

    docker-compose down
    # Edit .env file
    docker-compose up -d
    

CORS Issues

If you see CORS errors, the API proxy automatically adds CORS headers. Make sure:

  • The PASTEL_API_URL is accessible from the container
  • The API service is running
  • Network connectivity exists between containers

Container Logs

# View logs
docker-compose logs -f pastel-ui

# View API proxy logs specifically
docker-compose logs -f pastel-ui | grep -i proxy

Architecture

┌──────────────┐
│   Browser    │
└──────┬───────┘
       │ fetch('/api/pastel/colors/info')
       ▼
┌──────────────────────────────────┐
│   Next.js Container (port 3000)  │
│                                   │
│  ┌────────────────────────────┐  │
│  │   API Proxy Route          │  │
│  │   /api/pastel/[...path]    │  │
│  │                            │  │
│  │   Reads: PASTEL_API_URL    │  │
│  │   (runtime env var)        │  │
│  └────────────┬───────────────┘  │
└───────────────┼───────────────────┘
                │ proxy request
                ▼
┌──────────────────────────────────┐
│   Pastel API (port 3001)         │
│   /api/v1/colors/info            │
└──────────────────────────────────┘

Benefits of This Approach

No Rebuild Required - Change API URL by restarting container Environment Flexibility - Same image works in dev/staging/prod Network Isolation - Backend API doesn't need public exposure CORS Handled - Proxy adds necessary CORS headers Type Safety - TypeScript client works seamlessly with proxy

Migration from Old Approach

If you were using NEXT_PUBLIC_API_URL before:

Old (Build-time):

ARG NEXT_PUBLIC_API_URL
ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
RUN pnpm build

New (Runtime):

# No build args needed
RUN pnpm build

# Runtime configuration via environment
ENV PASTEL_API_URL=http://localhost:3001

The new approach requires a rebuild to switch to the proxy pattern, but after that, no more rebuilds are needed for configuration changes!