Skip to content

Docker Deployment

This guide covers deploying Rack Gateway using Docker, suitable for development, testing, and simple production deployments.

The official Docker image is available on Docker Hub:

Terminal window
docker pull docker.io/docspringcom/rack-gateway:latest
TagDescription
latestMost recent release
v0.x.xSpecific version (recommended for production)
Terminal window
docker network create rack-gateway-net
Terminal window
docker run -d \
--name postgres \
--network rack-gateway-net \
-e POSTGRES_USER=rack_gateway \
-e POSTGRES_PASSWORD=your-secure-password \
-e POSTGRES_DB=rack_gateway \
-v pgdata:/var/lib/postgresql/data \
postgres:16
Terminal window
docker run -d \
--name rack-gateway \
--network rack-gateway-net \
-p 8080:8080 \
-e DATABASE_URL=postgres://rack_gateway:your-secure-password@postgres:5432/rack_gateway \
-e DOMAIN=gateway.example.com \
-e APP_SECRET_KEY=$(openssl rand -base64 32) \
-e GOOGLE_CLIENT_ID=your-client-id \
-e GOOGLE_CLIENT_SECRET=your-client-secret \
-e GOOGLE_ALLOWED_DOMAIN=example.com \
-e RACK_TOKEN=your-convox-rack-token \
-e RACK_HOST=https://your-rack.convox.cloud \
-e ADMIN_USERS=admin@example.com \
docker.io/docspringcom/rack-gateway:latest
Terminal window
curl http://localhost:8080/api/v1/health

For a complete development environment, use Docker Compose:

docker-compose.yml
services:
postgres:
image: postgres:16
environment:
POSTGRES_USER: rack_gateway
POSTGRES_PASSWORD: development
POSTGRES_DB: rack_gateway
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U rack_gateway"]
interval: 5s
timeout: 5s
retries: 5
gateway:
image: docker.io/docspringcom/rack-gateway:latest
depends_on:
postgres:
condition: service_healthy
ports:
- "8080:8080"
environment:
DATABASE_URL: postgres://rack_gateway:development@postgres:5432/rack_gateway
DOMAIN: localhost:8080
DEV_MODE: "true"
APP_SECRET_KEY: dev-secret-key-32-bytes-minimum!!
GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET}
GOOGLE_ALLOWED_DOMAIN: ${GOOGLE_ALLOWED_DOMAIN}
RACK_TOKEN: ${RACK_TOKEN}
RACK_HOST: ${RACK_HOST}
ADMIN_USERS: ${ADMIN_USERS}
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/api/v1/health"]
interval: 10s
timeout: 5s
retries: 5
volumes:
pgdata:

Start with:

Terminal window
docker compose up -d
VariableDescriptionExample
DATABASE_URLPostgreSQL connection stringpostgres://user:pass@host:5432/db
DOMAINGateway domaingateway.example.com
APP_SECRET_KEY256-bit secret for sessionsopenssl rand -base64 32
GOOGLE_CLIENT_IDOAuth client IDFrom Google Cloud Console
GOOGLE_CLIENT_SECRETOAuth client secretFrom Google Cloud Console
GOOGLE_ALLOWED_DOMAINAllowed email domainexample.com
RACK_TOKENConvox rack API tokenFrom Convox
RACK_HOSTConvox rack URLhttps://rack.convox.cloud
VariableDefaultDescription
PORT8080HTTP listen port
DEV_MODEfalseEnable development mode
ADMIN_USERS-Comma-separated admin emails
RACK_ALIAS-Short rack name (e.g., staging)

See Environment Variables for the complete list.

Migrations run automatically on startup. To run them manually:

Terminal window
docker exec rack-gateway rack-gateway-api migrate

The gateway exposes health endpoints:

EndpointPurpose
/api/v1/healthBasic health check

Example health check configuration:

healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/api/v1/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
Terminal window
docker pull docker.io/docspringcom/rack-gateway:v0.1.0
services:
gateway:
deploy:
resources:
limits:
cpus: '1'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M

For production, run behind a reverse proxy with TLS:

server {
listen 443 ssl http2;
server_name gateway.example.com;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
location / {
proxy_pass http://gateway:8080;
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;
}
}

Configure regular PostgreSQL backups:

Terminal window
# Add to cron
0 * * * * docker exec postgres pg_dump -U rack_gateway rack_gateway | gzip > /backups/gateway-$(date +\%Y\%m\%d\%H).sql.gz

Configure Docker logging driver for production:

services:
gateway:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

Or use a centralized logging solution:

services:
gateway:
logging:
driver: "awslogs"
options:
awslogs-group: "rack-gateway"
awslogs-region: "us-east-1"
awslogs-stream: "gateway"

For local development, use DEV_MODE=true:

Terminal window
docker run -d \
-e DEV_MODE=true \
-e COOKIE_SECURE=false \
# ... other variables
docspringcom/rack-gateway:latest

Development mode enables:

  • Non-secure cookies (for HTTP)
  • Email logging instead of sending
  • Relaxed security checks

Check logs:

Terminal window
docker logs rack-gateway

Common issues:

ErrorCauseSolution
database connection failedPostgreSQL not reachableCheck DATABASE_URL and network
APP_SECRET_KEY requiredMissing secretGenerate with openssl rand -base64 32
OAuth client not configuredMissing Google credentialsSet GOOGLE_CLIENT_* variables

Verify PostgreSQL is accessible:

Terminal window
docker exec -it postgres psql -U rack_gateway -d rack_gateway -c "SELECT 1"
Terminal window
docker ps -a
docker network inspect rack-gateway-net