-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
139 lines (134 loc) · 4.73 KB
/
Copy pathdocker-compose.yml
File metadata and controls
139 lines (134 loc) · 4.73 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
services:
postgres:
image: postgres:16-alpine
container_name: csgo_case_pg
restart: unless-stopped
environment:
POSTGRES_USER: csgo
POSTGRES_PASSWORD: csgo
POSTGRES_DB: csgo_case
ports:
- "5433:5432"
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U csgo -d csgo_case"]
interval: 5s
timeout: 3s
retries: 10
redis:
image: redis:7-alpine
container_name: csgo_case_redis
restart: unless-stopped
command: redis-server --appendonly yes
ports:
- "6380:6379"
volumes:
- redisdata:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 10
# ---------------------------------------------------------------------------
# The "scale" profile: the shape the site is meant to run in under load.
#
# Off by default — `pnpm infra:up` brings up Postgres and Redis and nothing
# else, because a connection pooler and a replica are pure overhead on a
# laptop running one API instance. `pnpm infra:up:scale` adds both, and then
# `pnpm test:load` measures something worth measuring.
# ---------------------------------------------------------------------------
# Transaction pooling in front of Postgres.
#
# Node keeps a connection pool per process, so `max_connections` is spent by
# the number of API instances times their pool size, and it runs out long
# before the database is actually busy. PgBouncer in transaction mode hands a
# server connection to a transaction rather than to a client, which turns a
# thousand idle application connections into a couple of dozen real ones.
#
# Prisma's prepared statements are what usually breaks behind a transaction
# pooler; pgbouncer has tracked them since 1.21, and `MAX_PREPARED_STATEMENTS`
# is what switches that on. The `?pgbouncer=true` flag in the URL is the belt
# to that braces.
pgbouncer:
image: edoburu/pgbouncer:latest
container_name: csgo_case_pgbouncer
profiles: ["scale"]
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
DATABASE_URL: "postgres://csgo:csgo@postgres:5432/csgo_case"
POOL_MODE: transaction
AUTH_TYPE: scram-sha-256
# Clients the pooler will accept, against the server connections it will
# actually open. That ratio is the entire point of running it.
MAX_CLIENT_CONN: 1000
DEFAULT_POOL_SIZE: 25
MIN_POOL_SIZE: 5
RESERVE_POOL_SIZE: 5
RESERVE_POOL_TIMEOUT: 3
MAX_PREPARED_STATEMENTS: 200
# A pooled connection that has been idle this long is closed rather than
# held against the server's limit.
SERVER_IDLE_TIMEOUT: 60
IGNORE_STARTUP_PARAMETERS: extra_float_digits,options
ADMIN_USERS: csgo
# The image listens on 5432 by default, which is the one port a Postgres
# pooler should not claim: it makes "is this the database or the pooler?"
# a question nobody can answer from a connection string.
LISTEN_PORT: 6432
ports:
- "6433:6432"
healthcheck:
test: ["CMD-SHELL", "PGPASSWORD=csgo psql -h 127.0.0.1 -p 6432 -U csgo -d pgbouncer -tAc 'SHOW POOLS' > /dev/null"]
interval: 10s
timeout: 5s
retries: 5
# A streaming read replica.
#
# It bootstraps itself: on an empty volume it takes a `pg_basebackup` of the
# primary and starts as a hot standby. It needs a replication role and a
# `pg_hba` line on the primary first, which `pnpm infra:replica:init` adds to
# the running primary without recreating it — a dev database that already
# holds a seeded catalogue must not have to be thrown away to gain a replica.
postgres-replica:
image: postgres:16-alpine
container_name: csgo_case_pg_replica
profiles: ["scale"]
restart: unless-stopped
user: postgres
depends_on:
postgres:
condition: service_healthy
environment:
PGPASSWORD: replica
PGUSER: replicator
entrypoint:
- sh
- -c
- |
set -e
if [ ! -s "$$PGDATA/PG_VERSION" ]; then
echo "Taking a base backup of the primary..."
rm -rf "$$PGDATA"/*
# -R writes standby.signal and primary_conninfo, which is what makes
# this a streaming standby rather than a one-off copy.
pg_basebackup -h postgres -p 5432 -D "$$PGDATA" -Fp -Xs -R -P
chmod 0700 "$$PGDATA"
fi
exec postgres
ports:
- "5434:5432"
volumes:
- pgreplica:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U replicator -d csgo_case"]
interval: 10s
timeout: 5s
retries: 10
volumes:
pgdata:
redisdata:
pgreplica: