Complete guide to deploying the GraphQL proxy server using Docker containers.
- Docker Engine 20.10+
- Docker Compose (recommended)
docker run -d \
--name graphql-proxy \
-p 5001:5001 \
-e UPSTREAM_GRAPHQL_ENDPOINT=https://api.example.com/graphql \
-e GRAPHQL_MODE=SETMODE \
--restart unless-stopped \
your-registry/graphql-proxy:latestCreate docker-compose.yml:
version: '3.8'
services:
graphql-proxy:
image: your-registry/graphql-proxy:latest
ports:
- "5001:5001"
environment:
- UPSTREAM_GRAPHQL_ENDPOINT=https://api.example.com/graphql
- GRAPHQL_MODE=SETMODE
- AUTH_TOKEN=your-token-here
volumes:
- ./data:/app/data
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5001/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sDeploy with:
docker compose up -d# Build stage
FROM oven/bun:1 AS builder
WORKDIR /app
COPY package.json ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun run build
# Production stage
FROM oven/bun:1 AS runner
WORKDIR /app
# Copy built application
COPY --from=builder /app/server/index.ts ./server/
COPY --from=builder /app/package.json ./
COPY --from=builder /app/node_modules ./node_modules
# Create data directories
RUN mkdir -p /app/data/graphql-cache /app/data/mutation-queue
# Set environment
ENV NODE_ENV=production
ENV PORT=5001
EXPOSE 5001
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:5001/health || exit 1
CMD ["bun", "run", "server/index.ts"]# Build image
docker build -t graphql-proxy .
# Tag for registry
docker tag graphql-proxy your-registry/graphql-proxy:latest
# Push to registry
docker push your-registry/graphql-proxy:latestversion: '3.8'
services:
graphql-proxy:
image: your-registry/graphql-proxy:latest
container_name: graphql-proxy-prod
ports:
- "80:5001"
environment:
- NODE_ENV=production
- PORT=5001
- UPSTREAM_GRAPHQL_ENDPOINT=https://api.production.com/graphql
- AUTH_TOKEN=${AUTH_TOKEN}
- GRAPHQL_MODE=SETMODE
- CORS_ORIGIN=https://yourapp.com
volumes:
- graphql_cache:/app/data/graphql-cache
- graphql_queue:/app/data/mutation-queue
- graphql_db:/app/data/local-db.json
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5001/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
networks:
- proxy
volumes:
graphql_cache:
driver: local
graphql_queue:
driver: local
graphql_db:
driver: local
networks:
proxy:
driver: bridgeCreate .env.prod:
# Production environment
NODE_ENV=production
PORT=5001
UPSTREAM_GRAPHQL_ENDPOINT=https://api.production.com/graphql
AUTH_TOKEN=your-production-token
GRAPHQL_MODE=SETMODE
CORS_ORIGIN=https://yourapp.com
# Storage paths
CACHE_DIR=/app/data/graphql-cache
QUEUE_DIR=/app/data/mutation-queue
LOCAL_DB_PATH=/app/data/local-db.jsonversion: '3.8'
services:
graphql-proxy:
# ... proxy configuration
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/ssl:ro
depends_on:
- graphql-proxy
networks:
- proxyNginx configuration (nginx.conf):
events {
worker_connections 1024;
}
http {
upstream graphql_backend {
server graphql-proxy:5001;
}
server {
listen 80;
server_name your-domain.com;
# Redirect to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /etc/ssl/cert.pem;
ssl_certificate_key /etc/ssl/key.pem;
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
# GraphQL endpoint
location /graphql {
proxy_pass http://graphql_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeout settings
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Health check
location /health {
proxy_pass http://graphql_backend;
}
}
}version: '3.8'
services:
graphql-proxy:
image: your-registry/graphql-proxy:latest
deploy:
mode: replicated
replicas: 3
restart_policy:
condition: on-failure
environment:
- UPSTREAM_GRAPHQL_ENDPOINT=https://api.production.com/graphql
- GRAPHQL_MODE=GETMODE # Read-only for scaling
networks:
- proxy
load-balancer:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./load-balancer.conf:/etc/nginx/nginx.conf:ro
depends_on:
- graphql-proxy
networks:
- proxyLoad balancer configuration:
events {
worker_connections 1024;
}
http {
upstream graphql_proxies {
server graphql-proxy:5001;
}
server {
listen 80;
server_name api.your-domain.com;
location / {
proxy_pass http://graphql_proxies;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}services:
graphql-proxy:
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5001/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sservices:
graphql-proxy:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels: "service"
environment:
- NODE_ENV=productionversion: '3.8'
services:
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
networks:
- monitoring
graphql-proxy:
# ... proxy configuration
environment:
- METRICS_PORT=9090
networks:
- proxy
- monitoring# Use non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
USER nodejsservices:
graphql-proxy:
environment:
- UPSTREAM_GRAPHQL_ENDPOINT=https://api.production.com/graphql
secrets:
- auth_token
secrets:
auth_token:
file: ./secrets/auth_token.txtservices:
graphql-proxy:
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M# Check container logs
docker logs graphql-proxy
# Check container status
docker ps -a
# Inspect container
docker inspect graphql-proxy# Test health endpoint manually
docker exec graphql-proxy curl -f http://localhost:5001/health
# Check if port is bound
docker exec graphql-proxy netstat -tlnp | grep 5001# Check volume permissions
docker run --rm -v graphql_cache:/data alpine ls -la /data
# Clean up volumes
docker volume rm $(docker volume ls -q | grep graphql)# Test upstream connectivity from container
docker exec graphql-proxy curl -f $UPSTREAM_GRAPHQL_ENDPOINT
# Check network configuration
docker network ls
docker network inspect proxy