Skip to content

Commit b5350b2

Browse files
authored
chore: add postgres docker-compose setup (#2903)
1 parent e04a4bf commit b5350b2

File tree

5 files changed

+298
-8
lines changed

5 files changed

+298
-8
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Create replication user for replica
5+
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
6+
CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'replicator';
7+
SELECT pg_create_physical_replication_slot('replication_slot_1');
8+
EOSQL
9+
10+
# Update pg_hba.conf to allow replication connections
11+
echo "host replication replicator 0.0.0.0/0 md5" >> "$PGDATA/pg_hba.conf"
12+
13+
# Reload configuration
14+
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -c "SELECT pg_reload_conf();"
15+
16+
echo "Primary PostgreSQL configured for replication"
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/bash
2+
set -e
3+
4+
PGDATA="/var/lib/postgresql/data"
5+
6+
# Wait for primary to be ready
7+
until pg_isready -h postgres-primary -U spicedb 2>/dev/null; do
8+
echo "Waiting for primary to be ready..."
9+
sleep 2
10+
done
11+
12+
# Only run base backup if data directory is empty
13+
if [ ! -s "$PGDATA/PG_VERSION" ]; then
14+
echo "Setting up replica from primary..."
15+
16+
# Create base backup from primary
17+
PGPASSWORD=replicator pg_basebackup \
18+
-h postgres-primary \
19+
-D "$PGDATA" \
20+
-U replicator \
21+
-v \
22+
-P \
23+
-X stream \
24+
-R
25+
26+
# Set proper permissions
27+
chmod 700 "$PGDATA"
28+
chown -R postgres:postgres "$PGDATA"
29+
30+
echo "Replica setup complete"
31+
else
32+
echo "Data directory already initialized, skipping base backup"
33+
fi
34+
35+
# Start PostgreSQL as replica
36+
exec docker-entrypoint.sh postgres -c recovery_min_apply_delay=${REPLICA_APPLY_DELAY:-0}

docker-compose.postgres.yaml

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
---
2+
# FOR DEVELOPMENT ONLY. Run with
3+
# docker-compose -f docker-compose.postgres.yaml up --build
4+
services:
5+
postgres-primary:
6+
image: "postgres:16"
7+
container_name: "postgres-primary"
8+
environment:
9+
- "POSTGRES_USER=spicedb"
10+
- "POSTGRES_PASSWORD=spicedb"
11+
- "POSTGRES_DB=spicedb"
12+
- "POSTGRES_HOST_AUTH_METHOD=md5"
13+
ports:
14+
- "5432"
15+
volumes:
16+
- "postgres-primary-data:/var/lib/postgresql/data"
17+
- "./development/postgres/primary-init.sh:/docker-entrypoint-initdb.d/primary-init.sh"
18+
command: >
19+
postgres
20+
-c wal_level=replica
21+
-c max_wal_senders=10
22+
-c max_replication_slots=10
23+
-c hot_standby=on
24+
healthcheck:
25+
test: ["CMD-SHELL", "pg_isready -U spicedb"]
26+
interval: "3s"
27+
timeout: "3s"
28+
retries: 5
29+
restart: "unless-stopped"
30+
31+
postgres-replica:
32+
image: "postgres:16"
33+
container_name: "postgres-replica"
34+
environment:
35+
- "PGPASSWORD=replicator"
36+
- "REPLICA_APPLY_DELAY=100ms"
37+
ports:
38+
- "5432"
39+
volumes:
40+
- "postgres-replica-data:/var/lib/postgresql/data"
41+
- "./development/postgres/replica-init.sh:/replica-init.sh"
42+
depends_on:
43+
postgres-primary:
44+
condition: "service_healthy"
45+
entrypoint: ["/bin/bash", "/replica-init.sh"]
46+
healthcheck:
47+
test: ["CMD-SHELL", "pg_isready -U spicedb || exit 1"]
48+
interval: "5s"
49+
timeout: "3s"
50+
retries: 10
51+
restart: "unless-stopped"
52+
53+
migrate:
54+
depends_on:
55+
postgres-primary:
56+
condition: "service_healthy"
57+
build: "."
58+
container_name: "migrate"
59+
environment:
60+
- "SPICEDB_DATASTORE_ENGINE=postgres"
61+
# Run migrations on primary
62+
- "SPICEDB_DATASTORE_CONN_URI=postgres://spicedb:spicedb@postgres-primary:5432/spicedb?sslmode=disable"
63+
command: "datastore migrate head"
64+
networks:
65+
- "default"
66+
67+
nginx:
68+
image: "nginx:latest"
69+
ports:
70+
- "50051:50051" # grpc
71+
- "8443:8443" # http
72+
volumes:
73+
- "./development/nginx.conf:/etc/nginx/nginx.conf"
74+
depends_on:
75+
spicedb-1:
76+
condition: "service_healthy"
77+
spicedb-2:
78+
condition: "service_healthy"
79+
80+
spicedb-1:
81+
container_name: "spicedb-1"
82+
build: "."
83+
command: "serve"
84+
restart: "no"
85+
ports:
86+
- "9090" # prometheus metrics
87+
- "50051" # grpc endpoint
88+
- "8443" # http endpoint
89+
- "50053" # dispatch endpoint
90+
environment:
91+
- "SPICEDB_LOG_FORMAT=json"
92+
- "SPICEDB_LOG_LEVEL=info"
93+
- "SPICEDB_HTTP_ENABLED=true"
94+
- "SPICEDB_GRPC_PRESHARED_KEY=foobar"
95+
- "SPICEDB_DATASTORE_ENGINE=postgres"
96+
- "SPICEDB_DATASTORE_CONN_URI=postgres://spicedb:spicedb@postgres-primary:5432/spicedb?sslmode=disable"
97+
- "SPICEDB_DATASTORE_READ_REPLICA_CONN_URI=postgres://spicedb:spicedb@postgres-replica:5432/spicedb?sslmode=disable"
98+
- "SPICEDB_DISPATCH_CLUSTER_ENABLED=true"
99+
- "SPICEDB_DISPATCH_UPSTREAM_ADDR=spicedb-2:50053"
100+
- "SPICEDB_OTEL_PROVIDER=otlpgrpc"
101+
- "SPICEDB_OTEL_SAMPLE_RATIO=1"
102+
- "SPICEDB_TELEMETRY_ENDPOINT="
103+
- "SPICEDB_GRPC_LOG_REQUESTS_ENABLED=false"
104+
- "SPICEDB_GRPC_LOG_RESPONSES_ENABLED=false"
105+
- "SPICEDB_STREAMING_API_RESPONSE_DELAY_TIMEOUT=0s"
106+
- "OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317"
107+
- "SPICEDB_DATASTORE_FOLLOWER_READ_DELAY_DURATION=2000ms"
108+
depends_on:
109+
migrate:
110+
condition: "service_completed_successfully"
111+
postgres-replica:
112+
condition: "service_healthy"
113+
otel-collector:
114+
condition: "service_started"
115+
healthcheck:
116+
test: ["CMD", "/bin/grpc_health_probe", "-addr=localhost:50051"]
117+
interval: "5s"
118+
timeout: "30s"
119+
retries: 3
120+
121+
spicedb-2:
122+
container_name: "spicedb-2"
123+
build: "."
124+
command: "serve"
125+
restart: "no"
126+
ports:
127+
- "9090" # prometheus metrics
128+
- "50051" # grpc endpoint
129+
- "8443" # http endpoint
130+
- "50053" # dispatch endpoint
131+
environment:
132+
- "SPICEDB_LOG_FORMAT=json"
133+
- "SPICEDB_LOG_LEVEL=info"
134+
- "SPICEDB_HTTP_ENABLED=true"
135+
- "SPICEDB_GRPC_PRESHARED_KEY=foobar"
136+
- "SPICEDB_DATASTORE_ENGINE=postgres"
137+
- "SPICEDB_DATASTORE_CONN_URI=postgres://spicedb:spicedb@postgres-primary:5432/spicedb?sslmode=disable"
138+
- "SPICEDB_DATASTORE_READ_REPLICA_CONN_URI=postgres://spicedb:spicedb@postgres-replica:5432/spicedb?sslmode=disable"
139+
- "SPICEDB_DISPATCH_CLUSTER_ENABLED=true"
140+
- "SPICEDB_DISPATCH_UPSTREAM_ADDR=spicedb-1:50053"
141+
- "SPICEDB_OTEL_PROVIDER=otlpgrpc"
142+
- "SPICEDB_OTEL_SAMPLE_RATIO=1"
143+
- "SPICEDB_TELEMETRY_ENDPOINT="
144+
- "SPICEDB_GRPC_LOG_REQUESTS_ENABLED=true"
145+
- "SPICEDB_GRPC_LOG_RESPONSES_ENABLED=false"
146+
- "SPICEDB_STREAMING_API_RESPONSE_DELAY_TIMEOUT=0s"
147+
- "OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317"
148+
- "SPICEDB_DATASTORE_FOLLOWER_READ_DELAY_DURATION=2000ms"
149+
depends_on:
150+
migrate:
151+
condition: "service_completed_successfully"
152+
postgres-replica:
153+
condition: "service_healthy"
154+
otel-collector:
155+
condition: "service_started"
156+
healthcheck:
157+
test: ["CMD", "/bin/grpc_health_probe", "-addr=localhost:50051"]
158+
interval: "5s"
159+
timeout: "30s"
160+
retries: 3
161+
162+
prometheus:
163+
image: "prom/prometheus:v2.47.0"
164+
command:
165+
- "--config.file=/etc/prometheus/prometheus.yaml"
166+
- "--storage.tsdb.path=/prometheus"
167+
volumes:
168+
- "./development/prometheus.yaml:/etc/prometheus/prometheus.yaml"
169+
ports:
170+
- "9091:9090" # Prometheus UI
171+
restart: "unless-stopped"
172+
173+
otel-collector:
174+
image: "otel/opentelemetry-collector:0.60.0"
175+
command: "--config /etc/otel-config.yaml"
176+
volumes:
177+
- "./development/otel-config.yaml:/etc/otel-config.yaml"
178+
ports:
179+
- "4317:4317" # OTLP gRPC
180+
- "8888" # Prometheus metrics for collector
181+
depends_on:
182+
- "tempo"
183+
restart: "unless-stopped"
184+
185+
loki:
186+
image: "grafana/loki:2.9.0"
187+
command: "-config.file=/etc/loki/loki.yaml"
188+
volumes:
189+
- "./development/loki.yaml:/etc/loki/loki.yaml"
190+
ports:
191+
- "3100" # Loki API
192+
restart: "unless-stopped"
193+
194+
tempo:
195+
image: "grafana/tempo:1.5.0"
196+
command: "-search.enabled=true -config.file=/etc/tempo.yaml"
197+
volumes:
198+
- "./development/tempo.yaml:/etc/tempo.yaml"
199+
restart: "unless-stopped"
200+
ports:
201+
- "4317" # OTLP gRPC
202+
- "3100" # tempo
203+
204+
grafana:
205+
image: "grafana/grafana:9.1.5-ubuntu"
206+
volumes:
207+
- "./development/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources"
208+
- "./development/grafana/provisioning/dashboards:/etc/grafana/provisioning/dashboards"
209+
- "./development/grafana/dashboards:/etc/grafana/dashboards"
210+
environment:
211+
- "GF_AUTH_ANONYMOUS_ENABLED=true"
212+
- "GF_AUTH_ANONYMOUS_ORG_ROLE=Admin"
213+
- "GF_AUTH_DISABLE_LOGIN_FORM=true"
214+
ports:
215+
- "3000:3000" # UI
216+
depends_on:
217+
- "tempo"
218+
- "prometheus"
219+
- "loki"
220+
restart: "unless-stopped"
221+
222+
volumes:
223+
postgres-primary-data:
224+
postgres-replica-data:

docker-compose.spanner.yaml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ services:
4444
volumes:
4545
- "./development/nginx.conf:/etc/nginx/nginx.conf"
4646
depends_on:
47-
- "spicedb-1"
48-
- "spicedb-2"
47+
spicedb-1:
48+
condition: "service_healthy"
49+
spicedb-2:
50+
condition: "service_healthy"
4951
spicedb-1:
5052
container_name: "spicedb-1"
5153
build: "."
@@ -79,7 +81,7 @@ services:
7981
otel-collector:
8082
condition: "service_started"
8183
healthcheck:
82-
test: ["CMD", "/bin/grpc_health_probe", "-addr=spicedb:50051"]
84+
test: ["CMD", "/bin/grpc_health_probe", "-addr=localhost:50051"]
8385
interval: "5s"
8486
timeout: "30s"
8587
retries: 3
@@ -96,7 +98,7 @@ services:
9698
environment:
9799
- "SPICEDB_LOG_FORMAT=json"
98100
- "SPICEDB_LOG_LEVEL=info"
99-
- "SPICEDB_HTTP_ENABLED=false"
101+
- "SPICEDB_HTTP_ENABLED=true"
100102
- "SPICEDB_GRPC_PRESHARED_KEY=foobar"
101103
- "SPICEDB_DATASTORE_ENGINE=spanner"
102104
- "SPICEDB_DATASTORE_CONN_URI=projects/test-project/instances/test-instance/databases/test-database"
@@ -115,6 +117,11 @@ services:
115117
condition: "service_completed_successfully"
116118
otel-collector:
117119
condition: "service_started"
120+
healthcheck:
121+
test: ["CMD", "/bin/grpc_health_probe", "-addr=localhost:50051"]
122+
interval: "5s"
123+
timeout: "30s"
124+
retries: 3
118125
prometheus:
119126
image: "prom/prometheus:v2.47.0"
120127
command:

docker-compose.yaml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ services:
4141
volumes:
4242
- "./development/nginx.conf:/etc/nginx/nginx.conf"
4343
depends_on:
44-
- "spicedb-1"
45-
- "spicedb-2"
44+
spicedb-1:
45+
condition: "service_healthy"
46+
spicedb-2:
47+
condition: "service_healthy"
4648
spicedb-1:
4749
container_name: "spicedb-1"
4850
build: "."
@@ -75,7 +77,7 @@ services:
7577
otel-collector:
7678
condition: "service_started"
7779
healthcheck:
78-
test: ["CMD", "/bin/grpc_health_probe", "-addr=spicedb:50051"]
80+
test: ["CMD", "/bin/grpc_health_probe", "-addr=localhost:50051"]
7981
interval: "5s"
8082
timeout: "30s"
8183
retries: 3
@@ -92,7 +94,7 @@ services:
9294
environment:
9395
- "SPICEDB_LOG_FORMAT=json"
9496
- "SPICEDB_LOG_LEVEL=info"
95-
- "SPICEDB_HTTP_ENABLED=false"
97+
- "SPICEDB_HTTP_ENABLED=true"
9698
- "SPICEDB_GRPC_PRESHARED_KEY=foobar"
9799
- "SPICEDB_DATASTORE_ENGINE=cockroachdb"
98100
- "SPICEDB_DATASTORE_CONN_URI=postgresql://root@crdb:26257/defaultdb?sslmode=disable"
@@ -110,6 +112,11 @@ services:
110112
condition: "service_completed_successfully"
111113
otel-collector:
112114
condition: "service_started"
115+
healthcheck:
116+
test: ["CMD", "/bin/grpc_health_probe", "-addr=localhost:50051"]
117+
interval: "5s"
118+
timeout: "30s"
119+
retries: 3
113120
prometheus:
114121
image: "prom/prometheus:v2.47.0"
115122
command:

0 commit comments

Comments
 (0)