docker.recipes

T3 Stack (Next.js + tRPC + Prisma)

intermediate

Full-stack TypeScript application with tRPC, Prisma, and NextAuth.

Overview

Next.js is a React framework for building production-ready web applications with server-side rendering, static site generation, and full-stack capabilities. Developed by Vercel and first released in 2016, Next.js has become the de facto standard for React applications requiring SEO optimization, fast initial page loads, and developer productivity. It provides file-based routing, automatic code splitting, and built-in optimization features that eliminate the need for complex webpack configurations. The T3 Stack combines Next.js with tRPC (TypeScript Remote Procedure Call), Prisma ORM, and NextAuth for authentication, creating an end-to-end type-safe development experience. This stack leverages PostgreSQL for reliable data persistence with ACID compliance, Redis for high-performance session storage and caching, and NGINX for production-grade reverse proxying and static asset serving. The combination delivers sub-millisecond cache responses through Redis while maintaining complex relational data integrity with PostgreSQL. Organizations choose this stack for its complete TypeScript integration from database schema to frontend components, eliminating runtime type errors and improving developer productivity. Startups building SaaS platforms, e-commerce sites, and content management systems benefit from the rapid development cycle, while enterprises appreciate the type safety, scalability through PostgreSQL's table partitioning, and NGINX's proven ability to handle high-traffic loads with minimal resource consumption.

Key Features

  • End-to-end type safety from Prisma database schema through tRPC API routes to Next.js frontend components
  • Server-side rendering and static site generation with automatic code splitting and image optimization
  • tRPC client-server communication with automatic TypeScript inference and runtime validation
  • NextAuth integration supporting OAuth providers like Discord, GitHub, and Google with session management
  • Prisma ORM with database migrations, relation management, and automatic TypeScript client generation
  • PostgreSQL JSONB support for flexible document storage alongside traditional relational data
  • Redis-based session persistence with sub-millisecond response times for user authentication
  • NGINX reverse proxy with HTTP/2 support, SSL termination, and static asset caching

Common Use Cases

  • 1SaaS platforms requiring user authentication, subscription management, and complex business logic
  • 2E-commerce applications with product catalogs, user accounts, and real-time inventory management
  • 3Content management systems with author permissions, publishing workflows, and SEO optimization
  • 4Social platforms with user profiles, real-time messaging, and activity feeds
  • 5Internal business dashboards with role-based access control and data visualization
  • 6API-first applications serving both web and mobile clients with type-safe endpoints
  • 7Multi-tenant applications requiring data isolation and user-specific customizations

Prerequisites

  • Docker and Docker Compose installed with at least 2GB available RAM for PostgreSQL and Redis
  • Node.js knowledge and familiarity with React components and TypeScript syntax
  • Basic understanding of SQL queries and relational database concepts for Prisma usage
  • OAuth application credentials from Discord or other providers for NextAuth configuration
  • Available ports 80, 443, 3000, and 5432 for NGINX, Next.js, and PostgreSQL services
  • SSL certificates for production HTTPS setup through NGINX reverse proxy

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 t3-app:
3 build:
4 context: .
5 dockerfile: Dockerfile
6 ports:
7 - "3000:3000"
8 environment:
9 DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
10 NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
11 NEXTAUTH_URL: http://localhost:3000
12 DISCORD_CLIENT_ID: ${DISCORD_CLIENT_ID}
13 DISCORD_CLIENT_SECRET: ${DISCORD_CLIENT_SECRET}
14 depends_on:
15 postgres:
16 condition: service_healthy
17 redis:
18 condition: service_started
19 networks:
20 - t3-net
21 restart: unless-stopped
22
23 postgres:
24 image: postgres:16-alpine
25 environment:
26 POSTGRES_USER: ${POSTGRES_USER}
27 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
28 POSTGRES_DB: ${POSTGRES_DB}
29 volumes:
30 - postgres_data:/var/lib/postgresql/data
31 healthcheck:
32 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
33 interval: 10s
34 timeout: 5s
35 retries: 5
36 networks:
37 - t3-net
38 restart: unless-stopped
39
40 redis:
41 image: redis:7-alpine
42 volumes:
43 - redis_data:/data
44 networks:
45 - t3-net
46 restart: unless-stopped
47
48 nginx:
49 image: nginx:alpine
50 ports:
51 - "80:80"
52 - "443:443"
53 volumes:
54 - ./nginx.conf:/etc/nginx/nginx.conf:ro
55 - ./certs:/etc/nginx/certs:ro
56 depends_on:
57 - t3-app
58 networks:
59 - t3-net
60 restart: unless-stopped
61
62volumes:
63 postgres_data:
64 redis_data:
65
66networks:
67 t3-net:
68 driver: bridge

.env Template

.env
1# PostgreSQL
2POSTGRES_USER=t3app
3POSTGRES_PASSWORD=secure_postgres_password
4POSTGRES_DB=t3app
5
6# NextAuth
7NEXTAUTH_SECRET=$(openssl rand -base64 32)
8
9# Discord OAuth (optional)
10DISCORD_CLIENT_ID=
11DISCORD_CLIENT_SECRET=

Usage Notes

  1. 1Create T3 app: npm create t3-app@latest
  2. 2T3 App at http://localhost:3000
  3. 3Run Prisma migrations: npx prisma migrate deploy
  4. 4Type-safe API with tRPC

Individual Services(4 services)

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

t3-app
t3-app:
  build:
    context: .
    dockerfile: Dockerfile
  ports:
    - "3000:3000"
  environment:
    DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
    NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
    NEXTAUTH_URL: http://localhost:3000
    DISCORD_CLIENT_ID: ${DISCORD_CLIENT_ID}
    DISCORD_CLIENT_SECRET: ${DISCORD_CLIENT_SECRET}
  depends_on:
    postgres:
      condition: service_healthy
    redis:
      condition: service_started
  networks:
    - t3-net
  restart: unless-stopped
postgres
postgres:
  image: postgres:16-alpine
  environment:
    POSTGRES_USER: ${POSTGRES_USER}
    POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    POSTGRES_DB: ${POSTGRES_DB}
  volumes:
    - postgres_data:/var/lib/postgresql/data
  healthcheck:
    test:
      - CMD-SHELL
      - pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}
    interval: 10s
    timeout: 5s
    retries: 5
  networks:
    - t3-net
  restart: unless-stopped
redis
redis:
  image: redis:7-alpine
  volumes:
    - redis_data:/data
  networks:
    - t3-net
  restart: unless-stopped
nginx
nginx:
  image: nginx:alpine
  ports:
    - "80:80"
    - "443:443"
  volumes:
    - ./nginx.conf:/etc/nginx/nginx.conf:ro
    - ./certs:/etc/nginx/certs:ro
  depends_on:
    - t3-app
  networks:
    - t3-net
  restart: unless-stopped

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 t3-app:
5 build:
6 context: .
7 dockerfile: Dockerfile
8 ports:
9 - "3000:3000"
10 environment:
11 DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
12 NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
13 NEXTAUTH_URL: http://localhost:3000
14 DISCORD_CLIENT_ID: ${DISCORD_CLIENT_ID}
15 DISCORD_CLIENT_SECRET: ${DISCORD_CLIENT_SECRET}
16 depends_on:
17 postgres:
18 condition: service_healthy
19 redis:
20 condition: service_started
21 networks:
22 - t3-net
23 restart: unless-stopped
24
25 postgres:
26 image: postgres:16-alpine
27 environment:
28 POSTGRES_USER: ${POSTGRES_USER}
29 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
30 POSTGRES_DB: ${POSTGRES_DB}
31 volumes:
32 - postgres_data:/var/lib/postgresql/data
33 healthcheck:
34 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
35 interval: 10s
36 timeout: 5s
37 retries: 5
38 networks:
39 - t3-net
40 restart: unless-stopped
41
42 redis:
43 image: redis:7-alpine
44 volumes:
45 - redis_data:/data
46 networks:
47 - t3-net
48 restart: unless-stopped
49
50 nginx:
51 image: nginx:alpine
52 ports:
53 - "80:80"
54 - "443:443"
55 volumes:
56 - ./nginx.conf:/etc/nginx/nginx.conf:ro
57 - ./certs:/etc/nginx/certs:ro
58 depends_on:
59 - t3-app
60 networks:
61 - t3-net
62 restart: unless-stopped
63
64volumes:
65 postgres_data:
66 redis_data:
67
68networks:
69 t3-net:
70 driver: bridge
71EOF
72
73# 2. Create the .env file
74cat > .env << 'EOF'
75# PostgreSQL
76POSTGRES_USER=t3app
77POSTGRES_PASSWORD=secure_postgres_password
78POSTGRES_DB=t3app
79
80# NextAuth
81NEXTAUTH_SECRET=$(openssl rand -base64 32)
82
83# Discord OAuth (optional)
84DISCORD_CLIENT_ID=
85DISCORD_CLIENT_SECRET=
86EOF
87
88# 3. Start the services
89docker compose up -d
90
91# 4. View logs
92docker 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/t3-stack-prisma/run | bash

Troubleshooting

  • NextAuth NEXTAUTH_URL must match your domain exactly, including protocol and port for callback URLs to work
  • Prisma migrate deploy fails: Ensure PostgreSQL health check passes and DATABASE_URL connection string is correct
  • tRPC query fails with network error: Check that t3-app service can reach postgres and redis containers on t3-net network
  • NGINX 502 Bad Gateway: Verify t3-app service is running on port 3000 and nginx.conf upstream configuration points to correct container name
  • Redis connection refused: Confirm redis service started successfully and Next.js Redis client uses 'redis:6379' as connection string
  • Build context errors: Ensure Dockerfile and package.json exist in current directory when running docker-compose up

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