We want:
.env file (environment variables)DATABASE_URL="postgresql://devarena:supersecretpassword@localhost:5432/devarenadb?schema=public"
JWT_ACCESS_SECRET=
JWT_REFRESH_SECRET=
RESEND_API_KEY =
ACCESS_TOKEN_EXPIRY=15m
REFRESH_TOKEN_EXPIRY=7d
OTP_TTL_SECONDS=120
OTP_MAX_ATTEMPTS=5
NODE_ENV=development
PORT = 5000
REDIS_URL=redis://default:supersecret@redis:6379
EMAIL_FROM ='devArena <team@company.in>'
POSTGRES_USER=devarena
POSTGRES_PASSWORD=supersecretpassword
POSTGRES_DB=devarenadb
POSTGRES_PORT=5432
REDIS_PORT=6379
We’ll inject these into our containers safely.
docker-compose.ymlHere’s a clean, CTO-grade compose setup:
version: '3.9'
services:
postgres:
image: postgres
container_name: devarena_postgres
restart: unless-stopped
env_file:
- .env
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ports:
- "${POSTGRES_PORT}:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: devarena_redis
restart: unless-stopped
ports:
- "${REDIS_PORT}:6379"
command: ["redis-server", "--requirepass", "supersecret", "--save", "", "--appendonly", "no"]
# 'save' and 'appendonly no' ensures pure in-memory mode for OTPs
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres_data:
redis_data:
| Component | Why it’s configured this way |
|---|---|
restart: unless-stopped |
Ensures containers reboot automatically on crash. |
postgres:16-alpine |
Lightweight, secure, latest stable Postgres. |
volumes |
Keeps Postgres data persistent across container restarts. |
redis:7-alpine |
Latest Redis with minimal footprint. |
--save "", --appendonly no |
Prevents Redis from persisting data — OTPs should die in memory. |
healthcheck |
Lets other services (like backend) wait until DB/Redis are “healthy.” |
Run:
docker-compose up -d