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>
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
- Client makes requests to
/api/pastel/* - Next.js API Route (
app/api/pastel/[...path]/route.ts) proxies requests to the backend - Backend API URL is read from
PASTEL_API_URLenvironment 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:
-
Check API URL:
docker exec pastel-ui env | grep PASTEL_API_URL -
Test API connectivity from container:
docker exec pastel-ui curl -f ${PASTEL_API_URL}/api/v1/health -
Check Docker network:
docker network inspect pastel-network -
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_URLis 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!