├── .gitignore ├── README.md ├── config-base ├── daemon.json ├── runner-instance.json ├── runner-shared.json └── web.json ├── config ├── daemon.json ├── runner-shared.json └── web.json ├── docker-build ├── Dockerfile └── README.md ├── docker-compose.yml ├── init.sql └── install.sh /.gitignore: -------------------------------------------------------------------------------- 1 | config 2 | sandbox-rootfs 3 | docker-build/syzoj 4 | docker-build/judge-v3 5 | data 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SYZOJ Docker 版 2 | --- 3 | 基于 docker-compose 实现的版本。 4 | 5 | 为了确保 runner 能够运行,需要在本机上进行配置: 6 | * 在 `/etc/default/grub` 中找到 `GRUB_CMDLINE_LINUX_DEFAULT` 一行,在引号内加入 `swapaccount=1`. 7 | * 执行 `update-grub` 后重启。 8 | 9 | 安装步骤如下: 10 | 1. clone 本 repo. 文件夹名必须是 `syzoj-docker`. 11 | 2. 获取 rootfs:在目录下执行 `mkdir sandbox-rootfs`, `docker create --name rootfs syzoj/rootfs:181202 bash`, `docker export rootfs | sudo tar xvf - -C sandbox-rootfs`, `docker rm rootfs`. 12 | 3. 启动:`docker-compose up -d`. 13 | 4. 进行初始配置:在当前目录下运行 `install.sh`. 14 | 5. 再次启动未启动成功的服务:`docker-compose up -d`. 15 | 16 | 可以在 docker-compose.yml 中修改向外开放的端口号。 17 | -------------------------------------------------------------------------------- /config-base/daemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "ServerUrl": "http://syzoj:5283/", 3 | "ServerToken": "@JUDGE_TOKEN@", 4 | "RabbitMQUrl": "amqp://rabbitmq/", 5 | "RedisUrl": "redis://redis:6379", 6 | "TestData": "/opt/syzoj/data/uploads/testdata", 7 | "Priority": 1, 8 | "DataDisplayLimit": 100, 9 | "TempDirectory": "/tmp" 10 | } 11 | -------------------------------------------------------------------------------- /config-base/runner-instance.json: -------------------------------------------------------------------------------- 1 | { 2 | "WorkingDirectory": "/opt/temp", 3 | "SandboxCgroup": "syzoj-1" 4 | } 5 | -------------------------------------------------------------------------------- /config-base/runner-shared.json: -------------------------------------------------------------------------------- 1 | { 2 | "RabbitMQUrl": "amqp://rabbitmq/", 3 | "TestData": "/opt/syzoj/data/uploads/testdata", 4 | "RedisUrl": "redis://redis:6379", 5 | "Priority": 1, 6 | "DebugMessageDisplayLimit": 5000, 7 | "OutputLimit": 104857600, 8 | "StderrDisplayLimit": 5120, 9 | "DataDisplayLimit": 128, 10 | "CompilerMessageLimit": 50000, 11 | "SpjTimeLimit": 1501, 12 | "SpjMemoryLimit": 256, 13 | "SandboxEnvironments": [ 14 | "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 15 | "HOME=/tmp" 16 | ], 17 | "SandboxUser": "nobody", 18 | "SandboxRoot": "/sandbox-rootfs", 19 | "BinaryDirectory": "/opt/binary" 20 | } 21 | -------------------------------------------------------------------------------- /config-base/web.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "SYZOJ", 3 | "hostname": "0.0.0.0", 4 | "port": "5283", 5 | "db": { 6 | "database": "syzoj", 7 | "username": "syzoj", 8 | "password": "123456", 9 | "host": "mysql", 10 | "migrated_to_typeorm": true, 11 | "cache_size": 1000 12 | }, 13 | "logo": { 14 | "url": null, 15 | "width": null, 16 | "height": null 17 | }, 18 | "register_mail": false, 19 | "email": { 20 | "method": "aliyundm", 21 | "options": { 22 | "AccessKeyId": "xxxx", 23 | "AccessKeySecret": "xxxx", 24 | "AccountName": "xxxx" 25 | } 26 | }, 27 | "upload_dir": "/opt/syzoj/data/uploads", 28 | "default": { 29 | "problem": { 30 | "time_limit": 1000, 31 | "memory_limit": 256 32 | }, 33 | "user": { 34 | "show": true, 35 | "rating": 1500 36 | } 37 | }, 38 | "sorting": { 39 | "ranklist": { 40 | "field": "rating", 41 | "order": "desc" 42 | }, 43 | "problem": { 44 | "field": "id", 45 | "order": "asc" 46 | } 47 | }, 48 | "limit": { 49 | "time_limit": 10000, 50 | "memory_limit": 1024, 51 | "data_size": 209715200, 52 | "testdata": 209715200, 53 | "submit_code": 102400, 54 | "submit_answer": 10485760, 55 | "custom_test_input": 20971520, 56 | "testdata_filecount": 100 57 | }, 58 | "page": { 59 | "problem": 50, 60 | "problem_statistics": 10, 61 | "judge_state": 10, 62 | "ranklist_index": 20, 63 | "ranklist": 50, 64 | "discussion": 10, 65 | "article_comment": 10, 66 | "contest": 10, 67 | "edit_contest_problem_list": 10, 68 | "edit_problem_tag_list": 10 69 | }, 70 | "enabled_languages": [ 71 | "cpp", 72 | "cpp11", 73 | "cpp17", 74 | "cpp-noilinux", 75 | "cpp11-noilinux", 76 | "cpp11-clang", 77 | "cpp17-clang", 78 | "c", 79 | "c-noilinux", 80 | "csharp", 81 | "java", 82 | "pascal", 83 | "python2", 84 | "python3", 85 | "nodejs", 86 | "ruby", 87 | "haskell" 88 | ], 89 | "filter_enabled_languages": [ 90 | "cpp", 91 | "cpp11", 92 | "cpp17", 93 | "cpp-noilinux", 94 | "cpp11-noilinux", 95 | "cpp11-clang", 96 | "cpp17-clang", 97 | "c", 98 | "c-noilinux", 99 | "csharp", 100 | "java", 101 | "pascal", 102 | "python2", 103 | "python3", 104 | "nodejs", 105 | "ruby", 106 | "haskell" 107 | ], 108 | "links": [ 109 | { 110 | "title": "LibreOJ", 111 | "url": "https://loj.ac/" 112 | } 113 | ], 114 | "session_secret": "@SESSION_SECRET@", 115 | "judge_token": "@JUDGE_TOKEN@", 116 | "redis": "redis://redis:6379", 117 | "email_jwt_secret": "@EMAIL_JWT_SECRET@", 118 | "google_analytics": "UA-XXXXXXXX-X", 119 | "gravatar_url": "https://cdn.v2ex.com/gravatar", 120 | "cdnjs_url": "built-in", 121 | "self_cdn_url": "built-in", 122 | "google_fonts": { 123 | "type": "built-in", 124 | "url": "" 125 | }, 126 | "no_cdn": false, 127 | "submissions_page_fast_pagination": false, 128 | "username_regex": "^[a-zA-Z0-9\\-\\_]+$", 129 | "site_for_download": "", 130 | "renderer_cache_size": "30000" 131 | } 132 | -------------------------------------------------------------------------------- /config/daemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "ServerUrl": "http://syzoj:5283/", 3 | "ServerToken": "hT1DT3k97oZFSa4l", 4 | "RabbitMQUrl": "amqp://rabbitmq/", 5 | "RedisUrl": "redis://redis:6379", 6 | "TestData": "/opt/syzoj/data/uploads/testdata", 7 | "Priority": 1, 8 | "DataDisplayLimit": 100, 9 | "TempDirectory": "/tmp" 10 | } 11 | -------------------------------------------------------------------------------- /config/runner-shared.json: -------------------------------------------------------------------------------- 1 | { 2 | "RabbitMQUrl": "amqp://rabbitmq/", 3 | "TestData": "/opt/syzoj/data/uploads/testdata", 4 | "RedisUrl": "redis://redis:6379", 5 | "Priority": 1, 6 | "DebugMessageDisplayLimit": 5000, 7 | "OutputLimit": 104857600, 8 | "StderrDisplayLimit": 5120, 9 | "DataDisplayLimit": 128, 10 | "CompilerMessageLimit": 50000, 11 | "SpjTimeLimit": 1501, 12 | "SpjMemoryLimit": 256, 13 | "SandboxEnvironments": [ 14 | "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 15 | "HOME=/tmp" 16 | ], 17 | "SandboxUser": "nobody", 18 | "SandboxRoot": "/sandbox-rootfs", 19 | "BinaryDirectory": "/opt/binary" 20 | } 21 | -------------------------------------------------------------------------------- /config/web.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "SYZOJ", 3 | "hostname": "0.0.0.0", 4 | "port": "5283", 5 | "db": { 6 | "database": "syzoj", 7 | "username": "syzoj", 8 | "password": "123456", 9 | "host": "mysql", 10 | "migrated_to_typeorm": true, 11 | "cache_size": 1000 12 | }, 13 | "logo": { 14 | "url": null, 15 | "width": null, 16 | "height": null 17 | }, 18 | "register_mail": false, 19 | "email": { 20 | "method": "aliyundm", 21 | "options": { 22 | "AccessKeyId": "xxxx", 23 | "AccessKeySecret": "xxxx", 24 | "AccountName": "xxxx" 25 | } 26 | }, 27 | "upload_dir": "/opt/syzoj/data/uploads", 28 | "default": { 29 | "problem": { 30 | "time_limit": 1000, 31 | "memory_limit": 256 32 | }, 33 | "user": { 34 | "show": true, 35 | "rating": 1500 36 | } 37 | }, 38 | "sorting": { 39 | "ranklist": { 40 | "field": "rating", 41 | "order": "desc" 42 | }, 43 | "problem": { 44 | "field": "id", 45 | "order": "asc" 46 | } 47 | }, 48 | "limit": { 49 | "time_limit": 10000, 50 | "memory_limit": 1024, 51 | "data_size": 209715200, 52 | "testdata": 209715200, 53 | "submit_code": 102400, 54 | "submit_answer": 10485760, 55 | "custom_test_input": 20971520, 56 | "testdata_filecount": 100 57 | }, 58 | "page": { 59 | "problem": 50, 60 | "problem_statistics": 10, 61 | "judge_state": 10, 62 | "ranklist_index": 20, 63 | "ranklist": 50, 64 | "discussion": 10, 65 | "article_comment": 10, 66 | "contest": 10, 67 | "edit_contest_problem_list": 10, 68 | "edit_problem_tag_list": 10 69 | }, 70 | "enabled_languages": [ 71 | "cpp", 72 | "cpp11", 73 | "cpp17", 74 | "cpp-noilinux", 75 | "cpp11-noilinux", 76 | "cpp11-clang", 77 | "cpp17-clang", 78 | "c", 79 | "c-noilinux", 80 | "csharp", 81 | "java", 82 | "pascal", 83 | "python2", 84 | "python3", 85 | "nodejs", 86 | "ruby", 87 | "haskell" 88 | ], 89 | "filter_enabled_languages": [ 90 | "cpp", 91 | "cpp11", 92 | "cpp17", 93 | "cpp-noilinux", 94 | "cpp11-noilinux", 95 | "cpp11-clang", 96 | "cpp17-clang", 97 | "c", 98 | "c-noilinux", 99 | "csharp", 100 | "java", 101 | "pascal", 102 | "python2", 103 | "python3", 104 | "nodejs", 105 | "ruby", 106 | "haskell" 107 | ], 108 | "links": [ 109 | { 110 | "title": "LibreOJ", 111 | "url": "https://loj.ac/" 112 | } 113 | ], 114 | "session_secret": "hT1DT3k97oZFSa4l", 115 | "judge_token": "hT1DT3k97oZFSa4l", 116 | "redis": "redis://redis:6379", 117 | "email_jwt_secret": "hT1DT3k97oZFSa4l", 118 | "google_analytics": "UA-XXXXXXXX-X", 119 | "gravatar_url": "https://cdn.v2ex.com/gravatar", 120 | "cdnjs_url": "built-in", 121 | "self_cdn_url": "built-in", 122 | "google_fonts": { 123 | "type": "built-in", 124 | "url": "" 125 | }, 126 | "no_cdn": false, 127 | "submissions_page_fast_pagination": false, 128 | "username_regex": "^[a-zA-Z0-9\\-\\_]+$", 129 | "site_for_download": "", 130 | "renderer_cache_size": "30000" 131 | } 132 | -------------------------------------------------------------------------------- /docker-build/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | RUN apt-get update -y && apt-get install -y ca-certificates curl gnupg && \ 3 | echo "deb https://deb.nodesource.com/node_8.x bionic main" >> /etc/apt/sources.list.d/nodesource.list && \ 4 | echo "deb-src https://deb.nodesource.com/node_8.x bionic main" >> /etc/apt/sources.list.d/nodesource.list && \ 5 | curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - 6 | RUN apt-get update -y && apt-get install -y p7zip-full clang-format python-pygments nodejs gcc g++ make libboost-filesystem-dev git 7 | ADD syzoj /opt/syzoj 8 | ADD judge-v3 /opt/judge-v3 9 | WORKDIR /opt/syzoj 10 | RUN npm install && (node_modules/.bin/tsc || true) 11 | WORKDIR /opt/judge-v3 12 | RUN npm install && (node_modules/.bin/tsc || true) 13 | WORKDIR / 14 | -------------------------------------------------------------------------------- /docker-build/README.md: -------------------------------------------------------------------------------- 1 | docker-build 2 | --- 3 | syzoj/syzoj:base 对应的 docker 镜像。 4 | 需要先运行 `git clone https://github.com/syzoj/syzoj` 与 `git clone https://github.com/syzoj/judge-v3`. 5 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | mysql: 4 | image: mariadb:10.3 5 | networks: 6 | - net 7 | environment: 8 | - MYSQL_ROOT_PASSWORD=123456 9 | volumes: 10 | - ./data/mysql:/var/lib/mysql 11 | redis: 12 | image: redis:5 13 | networks: 14 | - net 15 | volumes: 16 | - ./data/redis:/var/lib/redis 17 | command: ["redis-server", "--appendonly", "yes"] 18 | rabbitmq: 19 | image: rabbitmq 20 | networks: 21 | - net 22 | syzoj: 23 | image: syzoj/syzoj:base 24 | networks: 25 | - net 26 | volumes: 27 | - ./config:/opt/config 28 | - ./data/syzoj:/opt/syzoj/data 29 | command: ["node", "/opt/syzoj/app.js", "-c", "/opt/config/web.json"] 30 | working_dir: "/opt/syzoj" 31 | ports: 32 | - 5283:5283 33 | judger: 34 | image: syzoj/syzoj:base 35 | networks: 36 | - net 37 | volumes: 38 | - ./config:/opt/config 39 | - ./data/syzoj:/opt/syzoj/data 40 | working_dir: "/opt/judge-v3" 41 | command: ["node", "/opt/judge-v3/lib/daemon/index.js", "-c", "/opt/config/daemon.json", "-v"] 42 | runner: 43 | image: syzoj/syzoj:base 44 | networks: 45 | - net 46 | volumes: 47 | - ./config:/opt/config 48 | - ./data/syzoj:/opt/syzoj/data 49 | - ./sandbox-rootfs:/sandbox-rootfs 50 | - ./data/bin:/opt/binary 51 | - ./data/temp1:/opt/temp 52 | working_dir: "/opt/judge-v3" 53 | command: ["node", "/opt/judge-v3/lib/runner/index.js", "-s", "/opt/config/runner-shared.json", "-i", "/opt/config/runner-instance.json", "-v"] 54 | privileged: true 55 | networks: 56 | net: 57 | -------------------------------------------------------------------------------- /init.sql: -------------------------------------------------------------------------------- 1 | CREATE USER 'syzoj' IDENTIFIED BY '123456'; 2 | CREATE DATABASE `syzoj` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 3 | GRANT ALL PRIVILEGES ON `syzoj`.* TO 'syzoj'; 4 | FLUSH PRIVILEGES; 5 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cp -r config-base config 3 | SECRET=$(dd if=/dev/urandom | tr -dc A-Za-z0-9 | head -c${1:-16}) 4 | sed -i "s/@SESSION_SECRET@/$SECRET/g" config/web.json 5 | sed -i "s/@JUDGE_TOKEN@/$SECRET/g" config/web.json 6 | sed -i "s/@JUDGE_TOKEN@/$SECRET/g" config/daemon.json 7 | sed -i "s/@EMAIL_JWT_SECRET@/$SECRET/g" config/web.json 8 | docker run -i --rm --network syzoj-docker_net mariadb:10.3 mysql -uroot -p123456 -hmysql < init.sql 9 | --------------------------------------------------------------------------------