跳转至

安装教程

一、生成镜像,启动容器

首先准备一台装有 64 位 Linux 系统的计算机。

  • 选择 Linux 发行版时,建议使用 Ubuntu 系统。
  • 使用虚拟机上的 Linux 可能会影响测评效率,建议在实体机上安装 UOJ。

打开终端,进入仓库的主目录。这个教程里,我们会假设你的主目录名字就跟 UOJ 仓库的名字一样叫 “uoj”。也就是说,在进入主目录后,你当前目录名字叫 uoj,下面有 web、judger、problem 等等文件夹。

在主目录下执行下面的命令:

sudo docker-compose up

▶ 这是在做什么?

为了方便大家搭建 UOJ,我们发布的代码实际上是一份构建 UOJ 的 docker 镜像的代码,而这条命令简单来说就是先根据代码生成这个 UOJ 镜像,然后再把 UOJ 跑起来。

镜像简介:什么是 docker?什么是镜像?这里稍微解释一下哈。比方说,你的同学张三做了一款很好玩的游戏,想分享给你。于是他把自己在本地写好的游戏打了个压缩包 “游戏.rar”,然后发送给了你。这个压缩包就是类似 docker 里面叫镜像(image)的东西,而 docker-compose 命令会先执行我们写好的小脚本,来生成一个 “压缩包”。那么为什么不把 UOJ 直接打个 “uoj.rar” 发过来呢?理论上不是不行,但 UOJ 是个网站,结构比普通游戏更复杂一点点。比如 UOJ 需要超级管理员权限来安装所需的数据库、编译器等等,软件版本和配置文件都不能有差错。为了防止大家折腾,我们这里就将 UOJ 整个用 docker 给“包了起来”。你可以认为 docker 镜像是一种更高级的压缩包,里面不仅包含了 UOJ 自己的源代码,还包含了 UOJ 所需的运行环境的全部信息。

容器简介:当然,你光得到了 “游戏.rar” 的压缩包,这还不叫玩游戏,你得先解压,然后找到一个叫 “游戏.exe” 的东西,然后双击,弹出个炫酷的窗口,这才叫玩游戏。docker 也是类似的。你可以把 docker 理解为一种轻量级的虚拟机,它可以理解 docker 镜像里面记录的内容,并支持你在一台计算机内部搭建一台虚拟的 “小计算机” 来让这个镜像真的运行起来。这台虚拟的小计算机又称为容器(container),而运行容器的计算机我们称为宿主机(host)。在生成了 UOJ 镜像之后,上面的 docker-compose 命令会让 docker 启动一个容器来真正地运行 UOJ。这个容器就好似你又买了一台计算机一样,只是你还是用你现在操作的这台宿主机的鼠标键盘来操控它。容器跟外部的宿主机几乎是互不影响的:即使 UOJ 在小计算机里对 C++ 编译器的版本进行了一大通升级,你的宿主机上的 C++ 编译器也不会发生任何变化。当然,如果你勇于折腾,可以通过阅读源代码的方式来搞清楚运行环境的具体要求,在宿主机上抛弃 docker 直接安装 UOJ,其实也不是很复杂。

镜像 vs 容器:镜像和容器的关系,就好比 “游戏.rar” 和真正和你交互的那个炫酷的游戏窗口的关系。如果你早已理解了程序和进程的区别的话,镜像就好比是程序,而容器就好比是进程。你平时“写程序”其实是写程序的源代码,而编译是源代码生成程序的过程。程序“跑”起来了,实际上指的是操作系统根据你的程序启动了一个相应的执行程序的进程。生成一次程序之后,你可以多次启动进程来运行它。这里也是一样:生成了 UOJ 镜像就好比生成了一个叫 UOJ 的程序;你要运行它,就得启动容器,就好比你运行程序就得启动进程一样。你可以反复启动容器,但镜像只用生成一次。

这条命令的含义:docker-compose 是一个能让你更方便地使用 docker 的小工具。sudo docker-compose up 命令的意思是运行当前目录下我们写好的代码,生成一个 UOJ 的镜像,然后启动一个容器来把 UOJ 跑起来。当你安装完成后第二次执行该命令时,因为镜像已经生成过一遍了,就会跳过生产镜像的步骤,直接启动 UOJ 的容器。如果确实想重新生成镜像可以用 sudo docker-compose up --build 这条命令。

想了解更多?可以看看教程了解更多 docker 相关知识。

▶ 可能遇到的问题

  • 如果安装成功,最后几行应该会看到 Successfully tagged uoj_all:latestAttaching to uoj-allUOJ starts successfully 的字样。
  • 如果报错说没有 docker,请先安装一个 docker。如果报错说没有 docker-compose,请先安装一个 docker-compose。
  • 下载速度太慢?如果是 apt-get 下载太慢,可以修改文件 docker/sources.list 来更改 apt 软件源;如果是 composer 下载太慢,可以找到文件 docker/composer-setup.sh,修改 composer config repo.packagist composer https://xxxx 这一行中的 URL 来更改 composer 的源。
  • PEAR 报错信息刷屏是正常现象。如出现其他报错信息导致安装过程终止,请参考提示内容解决问题。如自行解决失败,请通过官方 QQ 群联系我们。
  • 简单来说,安装的过程就是个按顺序执行 docker/Dockerfile 文件里的命令的过程。如果中间某步挂掉了想 docker 容器内部看看,可以先找到挂掉前产生的镜像(通常来说是 sudo docker images 命令输出的最新的那个),然后用命令 sudo docker run -it --entrypoint /bin/bash <image-id> 切进去看看。注意这个镜像是 docker/Dockerfile 文件内导致安装挂掉的那步命令执行之前的镜像,而非挂掉的那一瞬间的镜像。

二、修改 DNS,访问 UOJ

打开一款你喜欢的编辑器,编辑文件 /etc/hosts,加入下面这一行文本:

127.0.0.1 local_uoj.ac

然后你就可以在浏览器里输入 http://local_uoj.ac 来访问你刚刚搭好的 UOJ 了!

▶ 这是在做什么?

在没有修改配置文件的情况下,访问 UOJ 的默认网址是 http://local_uoj.ac。但你直接访问这个网址得到的却是 404,为什么呢?

这是因为像 “http://local_uoj.ac” 这种网址只是个名字而已,你的计算机暂时还不知道它对应着互联网上的哪台机器。为了找到对应的机器,就要找个人像问路一样问问:“你好你好,请问 local_uoj.ac 怎么走?” 这个问路的过程叫 DNS 解析,这个友好的路人叫 DNS 服务器

DNS 服务器会答复你一个 IP 地址来表示你想找的那台机器的位置。你平时之所以能通过 “https://www.bilibili.com” 访问B站,就是因为你每次询问 DNS 服务器,它都会以 IP 地址的形式告诉你哪一台服务器是这个网址对应的B站服务器。

计算机网络比较复杂,就不展开更多了。总之你想访问 UOJ,要做的就是让 http://local_uoj.ac 这个网址对应到你刚刚启动 UOJ 容器的机器上,只是现在并没有哪台 DNS 服务器会做这样的 DNS 解析……但你可以自己动手把你的计算机上一个叫 /etc/hosts 的特殊文件以如前所述的方式进行修改。这样你的计算机就会知道:“哦,原来 local_uoj.ac 对应的是 127.0.0.1 这台机器啊,那我就不用找 DNS 服务器问了。” 这里 127.0.0.1 是一个 IP 地址,表示的是你现在操作的这台计算机。这个地址类似于 “我家”,每台机器上的 127.0.0.1 都是指的它自己。

如果你想让除自己这台计算机以外的机器也能正常访问 http://local_uoj.ac,你需要相应更改它们自己的 /etc/hosts 文件,不过 IP 地址要从 127.0.0.1 改成你搭建 UOJ 的机器的公网 IP 地址。

三、注册账号,上传题目

你现在可以试试 UOJ 是否能正常运作。

你在 UOJ 上注册的第一个账号会自动成为超级管理员,然后你就可以新建题目了!

在 problem 这个文件夹下有若干道样题,你可以动手上传试试。关于如何传题请参见题目文档

传题、测评都没问题的话,感觉就可以愉快使用 UOJ 了!

四、更改配置文件

UOJ 主要的配置文件在 UOJ 容器里的 /opt/web/uoj/app/.config.php,你可以根据自己的需要进行更改。

输入下面的命令进入 UOJ 的 docker 容器:

sudo docker exec -it uoj_all /bin/bash

然后会开启一个在容器内的终端。输入下面的命令就可以访问和修改配置文件了:

vim /opt/uoj/web/app/.config.php

一个例子如下:(如果本文档没有跟上代码更新的速度,请以该配置文件旁边的那个 .default-config.php 为准)

<?php
return [
    'database' => [                         // 数据库相关
        'database'  => 'app_uoj233',            // 数据库名称
        'username' => 'root',                   // 用户名
        'password' => '',                       // 密码
        'host' => '127.0.0.1'                   // 数据库主机名
    ],
    'web' => [                              // 网址相关
        'main' => [                             // 网站主体
            'protocol' => 'http',                   // 传输协议
            'host' => 'local_uoj.ac',               // 主机名
            'port' => 80                            // 端口
        ],
        'blog' => [                             // UOJ 博客 (用户名放前面之后成为完整的域名)
            'protocol' => 'http',                   // 传输协议
            'host' => 'blog.local_uoj.ac',          // 主机名
            'port' => 80                            // 端口
        ]
    ],
    'security' => [                         // 安全相关(不要动)
        'user' => [
            'client_salt' => 'salt0'
        ],
        'cookie' => [
            'checksum_salt' => ['salt1', 'salt2', 'salt3']
        ],
    ],
    'mail' => [                             // 邮件相关(SMTP 协议发送)
        'noreply' => [                          // noreply 邮箱
            'username' => 'noreply@none',
            'password' => 'noreply',
            'secure' => 'ssl',
            'host' => 'smtp.sina.com',
            'port' => 465
        ]
    ],
    'judger' => [                           // 测评相关(不要动)
        'socket' => [                           // 与测评机的 socket 服务器通讯的设置
            'port' => '233',                        // 端口
            'password' => 'password233'             // 认证密码(证明自己 UOJ 服务器)
        ]
    ],
    'svn' => [                              // svn 相关(不要动)
        'our-root' => [                         // 每个题目的 svn 仓库自带的仓库管理员
            'username' => 'our-root',               // 管理员用户名
            'password' => 'our-root'                // 密码
        ]
    ],
    'switch' => [                           // 一些开关
        'ICP-license' => false,                 // ICP 备案信息的显示
        'web-analytics' => false                // 网站流量统计(记 uoj.ac 名下……想统计自己的得改代码)
    ]
];

▶ 域名配置

UOJ 默认的访问地址是 http://local_uoj.ac。如果你想使用自己的域名,可以修改上面的 web 键对应的数组内容。

如果你是搭校内网站这种内网网站,你可以选择自己搭建校内的 DNS 解析服务,或者给每台内网的机器更改 hosts。

当然你也可以直接在 host 那里直接写 ip,就能直接通过 IP 访问了。

不过博客功能的话需要给每个用户的博客域名进行解析,最好是用一种叫泛解析的技术解决。如果不具备这个条件,可以参考开源社区版 UOJ 将博客改成以子目录形式呈现。

▶ 邮箱配置

noreply 邮箱的目的是发一些 OJ 相关的邮件,比如 svn 密码和 “找回密码”。

你可以注册一个邮箱小号把账号密码放在 mail 键对应的数组里。同时还要查一下邮件服务商的 SMTP 服务器名和端口。有些邮箱是需要手动开启某个开关才能允许 SMTP 发送邮件的,这一点也需要注意。