-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
136 lines (131 loc) · 5.32 KB
/
Copy pathdocker-compose.yml
File metadata and controls
136 lines (131 loc) · 5.32 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
# Brings up a complete, working Pixel Index from a clean checkout:
# cp .env.example .env # fill in the REQUIRED values
# docker compose up --build
#
# No external network, reverse proxy, or pre-existing infrastructure is
# required — everything here is self-contained. Putting a real domain and
# TLS in front of this is deliberately a separate step: see
# docs/deployment.md, which covers several reverse-proxy options — this
# file has no opinion about which one you use, or whether you use one at
# all.
#
# Where the official index actually runs is a deployment decision outside
# this repository, not a default this file encodes — see docs/deployment.md.
services:
postgres:
image: postgres:17-alpine
restart: unless-stopped
environment:
TZ: "${TZ:-Europe/Berlin}"
POSTGRES_USER: "${POSTGRES_USER:-pixel_index}"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required, see .env.example}"
POSTGRES_DB: "${POSTGRES_DB:-pixel_index}"
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-pixel_index}"]
interval: 5s
timeout: 5s
retries: 10
deploy:
resources:
limits:
memory: 512M
api:
build:
context: .
dockerfile: services/api/Dockerfile
args:
# Optional — see services/api/Dockerfile's ARG API_COMMIT. Unset
# bakes in no commit (GET / and GET /api/v1/meta report null), so
# a plain `docker compose build` still works. Pass this repo's own
# HEAD to have the API report which commit it's actually running:
# API_COMMIT=$(git rev-parse HEAD) docker compose build api
API_COMMIT: "${API_COMMIT:-}"
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
TZ: "${TZ:-Europe/Berlin}"
DATABASE_URL: "postgres://${POSTGRES_USER:-pixel_index}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required, see .env.example}@postgres:5432/${POSTGRES_DB:-pixel_index}"
RENDERER_URL: "${RENDERER_URL:-http://renderer:3000}"
PUBLIC_WEB_ORIGIN: "${PUBLIC_WEB_ORIGIN:?PUBLIC_WEB_ORIGIN is required, see .env.example}"
# Optional, and empty by default — only a platform that mints a fresh
# hostname per deploy (Vercel PR previews) needs it. See .env.example.
PUBLIC_WEB_ORIGIN_PATTERNS: "${PUBLIC_WEB_ORIGIN_PATTERNS:-}"
PUBLIC_API_ORIGIN: "${PUBLIC_API_ORIGIN:?PUBLIC_API_ORIGIN is required, see .env.example}"
DISCORD_CLIENT_ID: "${DISCORD_CLIENT_ID:?DISCORD_CLIENT_ID is required, see .env.example}"
DISCORD_CLIENT_SECRET: "${DISCORD_CLIENT_SECRET:?DISCORD_CLIENT_SECRET is required, see .env.example}"
SESSION_SECRET: "${SESSION_SECRET:?SESSION_SECRET is required, generate one with openssl rand -base64 48}"
BACKUP_API_KEY: "${BACKUP_API_KEY:-}"
DISCORD_ADMIN_IDS: "${DISCORD_ADMIN_IDS:-}"
DISCORD_GUILD_ID: "${DISCORD_GUILD_ID:-}"
DISCORD_MODERATOR_ROLE_IDS: "${DISCORD_MODERATOR_ROLE_IDS:-}"
DISCORD_INVITE_URL: "${DISCORD_INVITE_URL:-}"
# This secret belongs only in the API process. The web, renderer,
# Postgres and Pico never receive it.
DISCORD_OAUTH_TOKEN_ENCRYPTION_KEY: "${DISCORD_OAUTH_TOKEN_ENCRYPTION_KEY:-}"
DISCORD_MEMBERSHIP_CACHE_TTL_MS: "${DISCORD_MEMBERSHIP_CACHE_TTL_MS:-60000}"
# This compose file has no reverse proxy of its own in front of the
# api — see docs/deployment.md once you add one, and flip this to
# true so rate limiting keys on the real client, not the proxy.
API_TRUST_PROXY: "false"
ports:
- '${API_PORT_HOST:-3000}:3000'
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3000/ready').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 10s
timeout: 5s
start_period: 30s
retries: 5
deploy:
resources:
limits:
memory: 512M
renderer:
build:
context: .
dockerfile: services/renderer/Dockerfile
restart: unless-stopped
environment:
TZ: "${TZ:-Europe/Berlin}"
# No `ports:` — deliberately unreachable from the host or a browser (no
# CORS is configured on it). Only the api service talks to it, over the
# compose network. See services/api/README.md's note on preview-check.
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3000/ready').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 15s
timeout: 5s
start_period: 90s
retries: 5
deploy:
resources:
# A real browser, rendering user-controlled input — the one service
# here where an unbounded limit is a real risk, not just tidiness.
limits:
memory: 2G
cpus: '2'
web:
build:
context: .
dockerfile: apps/web/Dockerfile
args:
VITE_API_BASE_URL: "${VITE_API_BASE_URL:?VITE_API_BASE_URL is required, see .env.example}"
restart: unless-stopped
environment:
TZ: "${TZ:-Europe/Berlin}"
ports:
- '${WEB_PORT:-8080}:80'
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1/healthz"]
interval: 15s
timeout: 5s
start_period: 5s
retries: 3
deploy:
resources:
limits:
memory: 128M
volumes:
postgres-data: