docker.recipes

Production Go API Stack

advanced

Production Go API with Nginx, PostgreSQL, Redis caching, and structured logging

Overview

NGINX is a high-performance web server and reverse proxy that has become the backbone of modern web infrastructure, powering over 400 million websites worldwide. Originally developed to solve the C10K problem of handling 10,000 concurrent connections, NGINX uses an event-driven, asynchronous architecture that dramatically outperforms traditional process-based servers under high load conditions. This production stack combines NGINX's proven reverse proxy capabilities with Go's exceptional performance characteristics for building scalable APIs. The architecture leverages PostgreSQL's ACID compliance and advanced JSON support for reliable data persistence, while Redis provides sub-millisecond caching and session storage. Go's compiled binary approach, combined with NGINX's efficient connection handling, creates a stack capable of serving thousands of concurrent API requests with minimal resource overhead. This configuration targets engineering teams building high-throughput APIs that need production-grade reliability without the complexity of cloud-native orchestration. The stack excels for fintech applications requiring transaction integrity, e-commerce platforms with high concurrent user loads, and SaaS products where response time directly impacts user experience. The combination of Go's garbage collector optimizations and Redis caching can reduce database load by 80-90% while maintaining data consistency through PostgreSQL's robust transaction system.

Key Features

  • Event-driven NGINX architecture handles 10,000+ concurrent connections with minimal memory footprint
  • Go's compiled binary deployment eliminates runtime dependencies and reduces container size to under 20MB
  • PostgreSQL JSONB support enables hybrid relational-document queries with full ACID compliance
  • Redis Lua scripting enables atomic rate limiting and complex caching operations in sub-millisecond timeframes
  • Multi-stage Docker builds separate development dependencies from production runtime for enhanced security
  • Structured logging with Go's context package provides distributed tracing across NGINX, API, and database layers
  • PostgreSQL connection pooling through Go's database/sql package optimizes resource utilization under load
  • NGINX upstream health checks automatically route traffic away from failed API instances

Common Use Cases

  • 1E-commerce APIs requiring sub-100ms response times with Redis product catalog caching
  • 2Financial services applications needing PostgreSQL's ACID transactions for payment processing
  • 3Multi-tenant SaaS platforms using PostgreSQL row-level security and Redis session isolation
  • 4Real-time analytics dashboards leveraging PostgreSQL's window functions and Redis pub/sub
  • 5Content management systems utilizing PostgreSQL's full-text search with Redis query result caching
  • 6IoT data ingestion APIs using Go's goroutines for concurrent processing and PostgreSQL time-series storage
  • 7Mobile app backends requiring JWT authentication with Redis token blacklisting and PostgreSQL user management

Prerequisites

  • Minimum 2GB RAM (1GB for PostgreSQL, 512MB for Redis, 256MB for Go API, 256MB for NGINX)
  • Docker Engine 20.10+ with BuildKit support for multi-stage Dockerfile optimization
  • Available ports 80 (NGINX), 5432 (PostgreSQL), 6379 (Redis), or configure alternatives via environment variables
  • Understanding of Go module structure and PostgreSQL migration patterns for application development
  • Basic knowledge of NGINX upstream configuration for production load balancing scenarios
  • SSL certificate management if deploying with HTTPS termination at NGINX layer

For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms

docker-compose.yml

docker-compose.yml
1services:
2 nginx:
3 image: nginx:alpine
4 container_name: go-nginx
5 restart: unless-stopped
6 ports:
7 - "${NGINX_PORT:-80}:80"
8 volumes:
9 - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
10 depends_on:
11 - api
12
13 api:
14 build:
15 context: .
16 dockerfile: Dockerfile
17 target: production
18 container_name: go-api
19 restart: unless-stopped
20 environment:
21 - GIN_MODE=release
22 - PORT=8080
23 - DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}?sslmode=disable
24 - REDIS_URL=redis://redis:6379
25 - JWT_SECRET=${JWT_SECRET}
26 depends_on:
27 db:
28 condition: service_healthy
29 redis:
30 condition: service_started
31
32 db:
33 image: postgres:16-alpine
34 container_name: go-db
35 restart: unless-stopped
36 environment:
37 - POSTGRES_USER=${DB_USER}
38 - POSTGRES_PASSWORD=${DB_PASSWORD}
39 - POSTGRES_DB=${DB_NAME}
40 volumes:
41 - postgres_data:/var/lib/postgresql/data
42 healthcheck:
43 test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
44 interval: 5s
45 timeout: 5s
46 retries: 5
47
48 redis:
49 image: redis:7-alpine
50 container_name: go-redis
51 restart: unless-stopped
52 command: redis-server --appendonly yes
53 volumes:
54 - redis_data:/data
55
56 migrate:
57 build:
58 context: .
59 dockerfile: Dockerfile
60 target: migrate
61 container_name: go-migrate
62 environment:
63 - DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}?sslmode=disable
64 depends_on:
65 db:
66 condition: service_healthy
67 profiles:
68 - tools
69
70volumes:
71 postgres_data:
72 redis_data:

.env Template

.env
1# Go API Production Stack
2NGINX_PORT=80
3
4# Security
5JWT_SECRET=your-jwt-secret-key
6
7# Database
8DB_USER=goapi
9DB_PASSWORD=goapi_password
10DB_NAME=goapi_db

Usage Notes

  1. 1Multi-stage Dockerfile for small production image
  2. 2Run migrations: docker compose --profile tools up migrate
  3. 3API uses Redis for caching and rate limiting
  4. 4Nginx handles SSL termination and load balancing
  5. 5Health checks ensure proper startup order
  6. 6Binary compiled with CGO_ENABLED=0 for Alpine

Individual Services(5 services)

Copy individual services to mix and match with your existing compose files.

nginx
nginx:
  image: nginx:alpine
  container_name: go-nginx
  restart: unless-stopped
  ports:
    - ${NGINX_PORT:-80}:80
  volumes:
    - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
  depends_on:
    - api
api
api:
  build:
    context: .
    dockerfile: Dockerfile
    target: production
  container_name: go-api
  restart: unless-stopped
  environment:
    - GIN_MODE=release
    - PORT=8080
    - DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}?sslmode=disable
    - REDIS_URL=redis://redis:6379
    - JWT_SECRET=${JWT_SECRET}
  depends_on:
    db:
      condition: service_healthy
    redis:
      condition: service_started
db
db:
  image: postgres:16-alpine
  container_name: go-db
  restart: unless-stopped
  environment:
    - POSTGRES_USER=${DB_USER}
    - POSTGRES_PASSWORD=${DB_PASSWORD}
    - POSTGRES_DB=${DB_NAME}
  volumes:
    - postgres_data:/var/lib/postgresql/data
  healthcheck:
    test:
      - CMD-SHELL
      - pg_isready -U ${DB_USER}
    interval: 5s
    timeout: 5s
    retries: 5
redis
redis:
  image: redis:7-alpine
  container_name: go-redis
  restart: unless-stopped
  command: redis-server --appendonly yes
  volumes:
    - redis_data:/data
migrate
migrate:
  build:
    context: .
    dockerfile: Dockerfile
    target: migrate
  container_name: go-migrate
  environment:
    - DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}?sslmode=disable
  depends_on:
    db:
      condition: service_healthy
  profiles:
    - tools

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 nginx:
5 image: nginx:alpine
6 container_name: go-nginx
7 restart: unless-stopped
8 ports:
9 - "${NGINX_PORT:-80}:80"
10 volumes:
11 - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
12 depends_on:
13 - api
14
15 api:
16 build:
17 context: .
18 dockerfile: Dockerfile
19 target: production
20 container_name: go-api
21 restart: unless-stopped
22 environment:
23 - GIN_MODE=release
24 - PORT=8080
25 - DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}?sslmode=disable
26 - REDIS_URL=redis://redis:6379
27 - JWT_SECRET=${JWT_SECRET}
28 depends_on:
29 db:
30 condition: service_healthy
31 redis:
32 condition: service_started
33
34 db:
35 image: postgres:16-alpine
36 container_name: go-db
37 restart: unless-stopped
38 environment:
39 - POSTGRES_USER=${DB_USER}
40 - POSTGRES_PASSWORD=${DB_PASSWORD}
41 - POSTGRES_DB=${DB_NAME}
42 volumes:
43 - postgres_data:/var/lib/postgresql/data
44 healthcheck:
45 test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
46 interval: 5s
47 timeout: 5s
48 retries: 5
49
50 redis:
51 image: redis:7-alpine
52 container_name: go-redis
53 restart: unless-stopped
54 command: redis-server --appendonly yes
55 volumes:
56 - redis_data:/data
57
58 migrate:
59 build:
60 context: .
61 dockerfile: Dockerfile
62 target: migrate
63 container_name: go-migrate
64 environment:
65 - DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}?sslmode=disable
66 depends_on:
67 db:
68 condition: service_healthy
69 profiles:
70 - tools
71
72volumes:
73 postgres_data:
74 redis_data:
75EOF
76
77# 2. Create the .env file
78cat > .env << 'EOF'
79# Go API Production Stack
80NGINX_PORT=80
81
82# Security
83JWT_SECRET=your-jwt-secret-key
84
85# Database
86DB_USER=goapi
87DB_PASSWORD=goapi_password
88DB_NAME=goapi_db
89EOF
90
91# 3. Start the services
92docker compose up -d
93
94# 4. View logs
95docker compose logs -f

One-Liner

Run this command to download and set up the recipe in one step:

terminal
1curl -fsSL https://docker.recipes/api/recipes/production-go-api-stack/run | bash

Troubleshooting

  • Connection refused on port 80: Check NGINX_PORT environment variable and ensure no conflicts with existing services
  • Go API panics with database connection errors: Verify DATABASE_URL format and ensure PostgreSQL health check passes before API startup
  • Redis connection timeouts: Increase Redis maxclients setting or implement connection pooling in Go application code
  • NGINX 502 Bad Gateway: Confirm Go API is listening on port 8080 and check upstream configuration in nginx.conf
  • PostgreSQL migration failures: Run migrations separately using docker compose --profile tools up migrate before starting main services
  • High memory usage in Go API: Enable Go's garbage collector debug logging with GOGC environment variable tuning

Community Notes

Loading...
Loading notes...

Download Recipe Kit

Get all files in a ready-to-deploy package

Includes docker-compose.yml, .env template, README, and license

Ad Space