-
-
Notifications
You must be signed in to change notification settings - Fork 44
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
151 lines (144 loc) · 3.89 KB
/
Copy pathdocker-compose.yml
File metadata and controls
151 lines (144 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
version: '3.8'
services:
# ── NGINX load balancer ──────────────────────────────────────────
# Front door: rate limiting, response caching, request coalescing,
# gzip, and round-robin / least-conn fan-out to app replicas.
nginx:
image: nginx:1.27-alpine
container_name: crypto-news-lb
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
app:
condition: service_healthy
restart: unless-stopped
read_only: true
tmpfs:
- /var/cache/nginx
- /var/run
- /tmp
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE # Required to bind port 80
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost/nginx-health"]
interval: 10s
timeout: 3s
retries: 3
# ── Next.js API / SSR ───────────────────────────────────────────
# Scale with: docker compose up --scale app=4
app:
build:
context: .
dockerfile: Dockerfile
# No container_name — allows multiple replicas
expose:
- "3000"
environment:
- NODE_ENV=production
- PORT=3000
- REDIS_URL=redis://redis:6379
deploy:
replicas: 2
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.25'
memory: 128M
restart: unless-stopped
read_only: true
tmpfs:
- /tmp
- /app/.next/cache
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
depends_on:
redis:
condition: service_healthy
# ── Redis (cache + pub/sub backbone) ────────────────────────────
redis:
image: redis:7-alpine
container_name: crypto-news-redis
expose:
- "6379"
# Do NOT expose port 6379 to host in production — only internal traffic.
# Uncomment the next line for local debugging only:
# ports: ["6379:6379"]
volumes:
- redis_data:/data
command: >
redis-server
--appendonly yes
--maxmemory 256mb
--maxmemory-policy allkeys-lru
--tcp-backlog 511
--timeout 0
--tcp-keepalive 300
--rename-command FLUSHALL ""
--rename-command FLUSHDB ""
--rename-command DEBUG ""
--rename-command CONFIG ""
restart: unless-stopped
read_only: true
tmpfs:
- /tmp
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3
# ── WebSocket server (real-time streaming) ──────────────────────
# Scale with: docker compose up --scale websocket=2
websocket:
build:
context: .
dockerfile: Dockerfile.ws
# No container_name — allows multiple replicas
expose:
- "8080"
- "8081"
environment:
- PORT=8080
- WS_HEALTH_PORT=8081
- REDIS_URL=redis://redis:6379
- NEWS_API=http://app:3000
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8081/health"]
interval: 15s
timeout: 5s
retries: 3
start_period: 10s
deploy:
replicas: 2
resources:
limits:
cpus: '0.5'
memory: 256M
restart: unless-stopped
depends_on:
redis:
condition: service_healthy
volumes:
redis_data:
networks:
default:
name: crypto-news-network