| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- # WyOJ -- one-command deployment.
- #
- # docker compose up -d --build # fresh install (creates ./uoj_data)
- # ./judger/register-judger.sh # register the judger in judger_info
- # docker compose -f docker-compose.yml -f docker-compose.seed.yml up -d
- # # ... and seed the bundled production dump
- # docker compose logs -f uoj-web # apache + install output
- # docker compose logs -f uoj-judger # judge_client output
- # docker exec -it uoj-web bash # shell inside the web container
- #
- # Layout:
- # ./db/ uoj-db image: MySQL 5.7 + the current schema (app_uoj233.sql)
- # ./web/ uoj-web image: apache + php 7.4 + the WyOJ sources (+ judger tree)
- # ./judger/ uoj-judger image: python judge_client + the C++ sandbox
- # ./uoj_data/ runtime state (mysql datadir, /var/uoj_data, app/storage)
- #
- # `version` is kept so this still parses with the legacy python docker-compose;
- # service readiness is handled by install.sh's own wait loop, not by
- # depends_on conditions, for the same reason.
- #
- # SECURITY: the three secrets below are placeholders that are published in this
- # repository. Change JUDGER_PASSWORD / JUDGER_SOCKET_PASSWORD / the database
- # password together (and re-run ./judger/register-judger.sh) before putting this
- # anywhere public.
- version: '3'
- services:
- uoj-db:
- image: uoj-db:latest
- build:
- context: ./db/
- dockerfile: Dockerfile
- container_name: uoj-db
- restart: always
- volumes:
- - ./uoj_data/db/mysql:/var/lib/mysql
- environment:
- - MYSQL_DATABASE=app_uoj233
- - MYSQL_ROOT_PASSWORD=root
- healthcheck:
- test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-proot"]
- interval: 10s
- timeout: 5s
- retries: 12
- start_period: 30s
- uoj-web:
- image: uoj-web:latest
- build:
- # root context: the web image also needs ./judger (see web/Dockerfile)
- context: ./
- dockerfile: web/Dockerfile
- container_name: uoj-web
- restart: always
- depends_on:
- - uoj-db
- volumes:
- # uploads and .UOJSetupDone -- must persist across recreates
- - ./uoj_data/web/data:/var/uoj_data
- # submissions / pastes / tmp / judge_client.zip
- - ./uoj_data/web/storage:/opt/uoj/web/app/storage
- # generated on first boot from the environment below; kept on the host so
- # that rebuilding the image does not lose it
- - type: bind
- source: ./.config.local.php
- target: /opt/uoj/web/app/.config.php
- ports:
- - "80:80"
- # 3690 was published by the original file but nothing listens on it.
- # - "3690:3690"
- environment:
- - DATABASE_HOST=uoj-db
- - DATABASE_NAME=app_uoj233
- - DATABASE_USER=root
- - DATABASE_PASSWORD=root
- - JUDGER_SOCKET_PORT=2333
- - JUDGER_SOCKET_PASSWORD=_judger_socket_password_
- - SALT_0=_salt_0_
- - SALT_1=_salt_1_
- - SALT_2=_salt_2_
- - SALT_3=_salt_3_
- - UOJ_PROTOCOL=http
- uoj-judger:
- image: uoj-judger:latest
- build:
- context: ./judger/
- dockerfile: Dockerfile
- container_name: uoj-judger
- restart: always
- depends_on:
- - uoj-web
- # run_program.cpp drives the sandbox with ptrace(); without SYS_PTRACE the
- # first submission fails with "Judgement Failed". If the sandbox still
- # misbehaves under docker's default seccomp profile, add:
- # security_opt: ["seccomp:unconfined"]
- cap_add:
- - SYS_PTRACE
- volumes:
- # main_judger reads problem data directly instead of downloading it
- # (judge_client skips update_problem_data for judger_name == main_judger),
- # so share the web's data directory with it.
- - ./uoj_data/web/data:/var/uoj_data_copy:ro
- environment:
- - UOJ_PROTOCOL=http
- - UOJ_HOST=uoj-web
- - JUDGER_NAME=main_judger
- - JUDGER_PASSWORD=_judger_password_
- - JUDGER_SOCKET_PORT=2333
- - JUDGER_SOCKET_PASSWORD=_judger_socket_password_
- # No ports: the web reaches this container over the compose network via the
- # service name (`uoj-judger`), which is also what judger_info.ip must hold.
|