forked from ACMClassOJ/TesutoHime
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
179 lines (169 loc) · 5.55 KB
/
Copy pathdocker-compose.yml
File metadata and controls
179 lines (169 loc) · 5.55 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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# TesutoHime / ACMOJ - Docker deployment
#
# docker compose up -d --build # data services + web + scheduler
# docker compose --profile judger up -d # additionally build & run the judger
#
# Web UI: http://localhost:5080/OnlineJudge/
# MinIO console: http://localhost:9001/ (minioadmin / minioadmin)
services:
postgres:
image: postgres:16
environment:
POSTGRES_USER: oj
POSTGRES_PASSWORD: oj_password
POSTGRES_DB: oj
# Must match the web container's TZ — the schema stores naive
# datetimes, so a TZ mismatch reads back stamps that look hours
# stale and false-trips the proctor disconnect detector.
TZ: Asia/Shanghai
PGTZ: Asia/Shanghai
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U oj -d oj"]
interval: 5s
timeout: 5s
retries: 12
restart: unless-stopped
redis:
image: redis:7-alpine
command: ["redis-server", "--appendonly", "yes"]
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 12
restart: unless-stopped
minio:
image: minio/minio:latest
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
ports:
- "9000:9000" # S3 API
- "9001:9001" # web console
volumes:
- minio-data:/data
restart: unless-stopped
# One-shot job: waits for MinIO, creates buckets, makes oj-images public.
minio-init:
image: minio/mc:latest
depends_on:
- minio
entrypoint: ["/bin/sh", "/init.sh"]
volumes:
- ./docker/minio-init.sh:/init.sh:ro
restart: "no"
web:
build:
context: .
dockerfile: docker/Dockerfile.web
environment:
# Wall-clock TZ for the whole stack. The codebase stores contest
# times as naive datetimes whose values reflect the admin's
# browser local TZ; aligning the container clock here keeps
# ``datetime.now()`` comparisons numerically meaningful.
TZ: Asia/Shanghai
DB: postgresql+psycopg2://oj:oj_password@postgres:5432/oj
REDIS_HOST: redis
REDIS_WEB_DB: "0"
S3_PUBLIC_URL: http://localhost:9000/
S3_PUBLIC_ENDPOINT: http://localhost:9000/
S3_INTERNAL_ENDPOINT: http://minio:9000/
S3_ACCESS_KEY: minioadmin
S3_SECRET_KEY: minioadmin
SCHEDULER_BASE_URL: http://scheduler:5100/
SCHEDULER_AUTH: Bearer oj-internal-secret
CUSTOM_RUN_URL: http://judger:5200/
PROCTOR_BASE_URL: http://proctor2:5300/
PROCTOR_PUBLIC_URL: http://localhost:5300/
PROCTOR_INTERNAL_AUTH: Bearer oj-internal-secret
LIVEKIT_URL: ws://localhost:7880
LIVEKIT_API_KEY: oj_proctor_key
LIVEKIT_API_SECRET: oj_proctor_secret_change_me_to_64_chars_long_random_string_xxxxxxxxxxx
AWS_DEFAULT_REGION: us-east-1
GUNICORN_WORKERS: "4"
ports:
- "5080:5000"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
minio-init:
condition: service_completed_successfully
restart: unless-stopped
scheduler:
build:
context: .
dockerfile: docker/Dockerfile.scheduler
environment:
AWS_DEFAULT_REGION: us-east-1
depends_on:
redis:
condition: service_healthy
minio-init:
condition: service_completed_successfully
restart: unless-stopped
# LiveKit SFU — fans out student WebRTC streams to admin
# dashboards. Replaces the per-card mesh PeerConnections, which
# don't scale past ~25 simultaneous publishers in one tab.
livekit:
image: livekit/livekit-server:v1.7
command: ["--config", "/etc/livekit.yaml"]
ports:
- "7880:7880" # WebSocket signaling
- "7881:7881" # TCP media fallback
- "50000-50999:50000-50999/udp" # UDP media (room for ~200 pubs)
volumes:
- ./docker/livekit.yaml:/etc/livekit.yaml:ro
restart: unless-stopped
# proctor2: collects MediaRecorder chunks from proctored exam browsers
# and stitches them into per-session WebM files in oj-proctoring.
proctor2:
build:
context: .
dockerfile: docker/Dockerfile.proctor2
environment:
S3_INTERNAL_ENDPOINT: http://minio:9000/
S3_ACCESS_KEY: minioadmin
S3_SECRET_KEY: minioadmin
S3_PROCTOR_BUCKET: oj-proctoring
AWS_DEFAULT_REGION: us-east-1
PROCTOR_INTERNAL_AUTH: Bearer oj-internal-secret
PROCTOR_SPOOL: /var/lib/proctor2
ports:
- "5300:5300" # browsers POST media chunks here
volumes:
- proctor2-spool:/var/lib/proctor2
depends_on:
minio-init:
condition: service_completed_successfully
restart: unless-stopped
# Judger is experimental and heavy to build; see docker/Dockerfile.judger.
# Started only with: docker compose --profile judger up -d --build
judger:
build:
context: .
dockerfile: docker/Dockerfile.judger
privileged: true
profiles: ["judger"]
environment:
AWS_DEFAULT_REGION: us-east-1
# Reused by the entrypoint's auto-register step to write a row
# into ``judge_runner_v2``; no judge-side DB queries beyond that.
DB: postgresql+psycopg2://oj:oj_password@postgres:5432/oj
depends_on:
redis:
condition: service_healthy
minio-init:
condition: service_completed_successfully
restart: unless-stopped
volumes:
postgres-data:
redis-data:
minio-data:
proctor2-spool: