237 lines
5.8 KiB
Markdown
237 lines
5.8 KiB
Markdown
|
|
# 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
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# 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
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
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
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# .env
|
||
|
|
PASTEL_API_URL=http://pastel-api:3001
|
||
|
|
|
||
|
|
# docker-compose.yml will automatically read this
|
||
|
|
docker-compose up -d
|
||
|
|
```
|
||
|
|
|
||
|
|
## Local Development
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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:**
|
||
|
|
```bash
|
||
|
|
docker exec pastel-ui env | grep PASTEL_API_URL
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Test API connectivity from container:**
|
||
|
|
```bash
|
||
|
|
docker exec pastel-ui curl -f ${PASTEL_API_URL}/api/v1/health
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Check Docker network:**
|
||
|
|
```bash
|
||
|
|
docker network inspect pastel-network
|
||
|
|
```
|
||
|
|
|
||
|
|
4. **Update API URL without rebuild:**
|
||
|
|
```bash
|
||
|
|
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
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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):**
|
||
|
|
```dockerfile
|
||
|
|
ARG NEXT_PUBLIC_API_URL
|
||
|
|
ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
|
||
|
|
RUN pnpm build
|
||
|
|
```
|
||
|
|
|
||
|
|
**New (Runtime):**
|
||
|
|
```dockerfile
|
||
|
|
# 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!
|