在Linux机器上部署UOJ评测系统

文章目录

  • 前言
    • 初版前言
    • 两年后补充前言
  • 部署前的准备
    • UOJ结构与概念简介
      • UOJ开源历史
      • UOJ系统结构
      • 概念解释
    • 物质准备
  • 部署
    • 客户机先决条件安装
      • 说明
      • Ubuntu软件源更新
      • docker运行先决条件部署
    • 获取UOJ社区版Docker镜像
      • 从GitHub上获取并制作Docker镜像
      • 从DockerHub上获取Docker镜像
    • 使用镜像创建UOJ系统容器
    • 部署图形化管理系统
      • 安装KodExplorer图形界面
      • 安装phpMyAdmin图形化数据库管理系统
  • 管理UOJ容器
    • 打开容器
    • 进入容器终端
    • 关闭容器
    • 删除容器
    • 将容器导出为镜像
    • 启动和关闭容器中的服务
      • Apache2
      • MySQL
  • 更多内容

前言

初版前言

学校里想要部署一套OJ,然后就选了UOJ。

但是由于服务器还要一段时间(永远)才能到,所以就先拿了一台电脑作为试验机进行内网部署测试。

非常感谢以下大佬:

  • vfleaking 无私开放了UOJ的源码
  • 阮行止 维护社区版本UOJ源码并且提供大量帮助
  • 湘江一桥 维护社区版本UOJ源码并且提供大量帮助
  • 其他提供帮助的人

这篇部署教程就是第一来帮助更多人,第二。。。帮自己在正式部署的时候不会乱了阵脚。。。

另外,引用了部分UOJ部署指北中的内容。

两年后补充前言

现在我已经是第四次对这篇博客进行修改了。不过不同于前三次,这一次进行了巨大的修改,主要是把里面的一些不正确的、过时的东西给修正了。

这篇文章刚刚被写出来的时候还是题主在高二时期,那时候对于Linux系统几乎没有什么理解,对终端、命令、Docker系统甚至是网站服务一无所知。不过即便是在那样的条件下,我还是坚持研究并成功积累了一些部署和开发的经验。

本着分享的原则,我写下了两年前的这篇博客,也是为了防止自己忘掉这些经历。

但是水平有限是硬伤。许多词汇并不专业,甚至错误连篇。

写下这篇补充前言的时候,题主已是一名软件工程学院的大一学生,已经积累了一部分Linux知识和网站搭建的能力,对这些东西的理解更深了。

翻出多年前的博客,我决定将它修改成正确的、对新手真正有帮助的博客。

本博客的面向人群是缺乏部署经验的新手开发者,对于高手而言可能内容比较冗杂,可以酌情跳过。如果您发现文档中的任何问题,请在下方评论区进行回复,谢谢。

另外,本博客为原创博客。您可以随意转载本博客,但是请务必附上题主AdemJensen的原始博客地址或者个人页面。如果被我发现抄袭行为的,一律进行举报,感谢您对原创作者的尊重。

部署前的准备

UOJ结构与概念简介

UOJ开源历史

2016年10月3日,vfleaking在UOJ博客上发布了开源公告 ,UOJ从此正式成为开源项目。GitHub地址为:https://github.com/vfleaking/uoj 。

2017年中旬,阮行止、ceba、Masco Skray等几位大佬由于怀揣着相同的想法——将UOJ维护成一个比官方版本更易用的社区版本,创建了UOJ开发社区,并在GitHub上发布了社区版源码。

2017年下旬,阮行止大佬为UOJ社区版编写了部署指北文档,帮助更多新手部署UOJ。

至今,UOJ社区版和UOJ官方版都在进行维护。但是相比之下,社区版本的系统添加了很多非常实用的功能,因此本博客所描述的部署步骤均建立在社区版本的UOJ系统上。

UOJ系统结构

最初UOJ被设计的时候,出于安全考虑,网站服务器和数据库都被放置在Docker容器中(vfleaking的UOJ系统是部署在阿里云上的)。

Docker 是一个开源的应用容器引擎,可以理解为类似于VMWare或者VirtualBox那样的虚拟机软件。Docker创建出来的类似于“虚拟机”的东西名字叫“容器”,容器通常是没有图形化界面的。

UOJ将一个轻量化的ubuntu14系统、php5、apache2、MySQL和评测机服务集成在一个Docker容器中。

这样做的好处是,当有人攻击服务器的时候,实际被攻击的是Docker容器,而服务器本体不会受到影响。由于Docker容器能够较为方便的备份、创建、恢复,因此服务的提供上来讲更为稳定。

不过缺点也有的,几乎就是虚拟机的缺点:占用资源更多、运行速度可能较慢等等(Docker容器和虚拟机还是有区别的,直接结果就是Docker容器的效率比虚拟机高,占用资源比虚拟机少,但相比起实体机还是相对差一些)。

在2017年末和2018年初的时候,社区曾经有人(湘江一桥大佬,他为本博客的编写也提供了巨大的技术指导)尝试将vfleaking打包的Docker安装脚本提取出来,并制作实体机安装包,目前进度不详。有兴趣的话可以加入社区群了解一下(社区群号在UOJ部署指北中)。

另外,UOJ的网站前端框架是BootStrap,后端是魔改的Laravel(改到连版本都认不出来啦,vfleaking真的是厉害)

概念解释

  • 客户机:指的是你用来部署UOJ的操作系统(就是你给你电脑开机看到的那个系统)

  • 容器:指Docker创建出来的类似于“虚拟机”的东西。

  • 镜像:可以理解为一种“安装光盘”,可以用于创建Docker容器。Docker容器中的全部状态和内容都会被保存,有点类似于虚拟机软件中“挂起”的“虚拟机”。

物质准备

  • 服务器一部(也可以是阿里云或者各种云,只要是Linux系统就可以了)

  • Ubuntu 系统(推荐Ubuntu最新版或者Ubuntu Server最新版。也可以是其他Linux系统,不过软件源等东西就不一样了)

  • UOJ部署指北一份

  • UOJ官方文档一份

部署

客户机先决条件安装

我们需要安装好Ubuntu的各种服务。

说明

如未特殊指出,本文中的bash命令均是在root(管理员)用户下进行的,您可以使用以下命令来进入管理员模式:

sudo -s

按下回车后,系统会提示你输入密码。你会发现密码输不进去,其实是输进去了,只是系统不让你看见而已。使用小键盘时请注意取消NumberLock锁定,否则数字是输不进去的。

另外,如未说明,下面的指令均是在客户机的终端中进行。当容器创建完毕后,终端将会分客户机终端和容器终端。

Ubuntu软件源更新

更新软件源以确保获取最新的docker。

apt update

然后更新机上的软件。这一步其实无所谓,而且比较花时间,可以跳过。

apt upgrade

docker运行先决条件部署

下面部署沙盒系统docker。

apt install docker.io

使用以下指令为Docker添加DockerHub加速(否则部署可能会失败,因为DockerHub也是国外站点):

apt install curl
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://3a834d99.m.daocloud.io

然后重启Docker服务以应用DockerHub加速设置。

service docker restart

获取UOJ社区版Docker镜像

UOJ社区版现在比较厉害,有两种获取系统安装镜像的方式。

  • 一种是从GitHub上抓取,这种方法可以保证你抓取到的是最新版的UOJ,但是需要运行install脚本创建Docker镜像。

  • 另一种是从DockerHub上抓取,这样抓取相对比较方便,但是版本跟不上最新的UOJ(而且密码找回功能可能有问题,需要手动修复),并且镜像安装出来的系统不支持Java代码评测。

从GitHub上获取并制作Docker镜像

可以登录这个地址下载安装源代码。

或者执行下面的指令获取源代码:

git clone https://github.com/UniversalOJ/UOJ-System.git

刚才那条指令建议在普通用户状态执行,否则下载的文件会有权限,导致无法修改。

您可以使用exit命令来退出管理员模式,也可以再打开一个新的终端。

然后在终端使用 cd命令 转到你刚才下载的文件夹。

如果您需要支持Java代码评测,请下载这两个文件:

  • jdk-7u76-linux-x64.tar.gz
  • jdk-8u31-linux-x64.tar.gz

然后把它们放进UOJ-System/docker目录,替换掉jdk-7u76-linux-x64.tar.gzjdk-8u31-linux-x64.tar.gz

在2017-4-23之前的版本是在 UOJ-System 文件夹中。你应该能看到这个文件夹中有一个install文件。

请注意,UOJ-System/docker文件夹中也有一个重名的文件,千万不要运行那个!

转到UOJ-System文件夹,然后输入指令:

sudo bash ./install

安装脚本将会自动开始获取需要的内容并创建镜像。如果创建过程顺利的话,您将会看到Successfully built字样。社区版的安装脚本会将创建出来的镜像自动命名为uoj(官方原版需要使用后面脚本输出的哈希值)。

从DockerHub上获取Docker镜像

只需要运行下面的命令即可:

sudo docker pull universaloj/uoj-system:stable

使用镜像创建UOJ系统容器

  • 如果您刚才使用Github获取的源代码并制作了镜像,请运行以下命令:
sudo docker run --name uoj -dit -p 80:80 -p 3690:3690 -p 5678:5678 -p 6789:6789 --cap-add SYS_PTRACE uoj
  • 如果您从DockerHub中获取了镜像,请运行以下命令:
sudo docker run --name uoj -dit -p 80:80 -p 3690:3690 -p 5678:5678 -p 6789:6789 --cap-add SYS_PTRACE universaloj/uoj-system:stable

其中的参数意义如下:

--name XXX参数指定创建后的容器名字叫什么。你可以改成你喜欢的名字,但是不要有空格或者奇怪的符号。

--cap-add SYS_PTRACE参数在当前版本是必不可少的,它是评测系统运行的必备条件,意思是允许容器中的程序使用ptrace函数(代码的评测就是使用ptrace函数来进行的)。

-p XXXX:XXXX参数为创建的Docker容器添加客户机的端口映射,格式为-p 客户机端口:容器端口

其中,端口映射不可缺少的是容器内80端口和3690端口,它们分别的作用是网站主界面和SVN数据管理仓库。

SVN仓库的作用是管理题目数据和进行UOJ网站本体的开发。有关的更多内容还请参见部署指北。

我这里比部署指北多了端口5678和6789,分别用于部署KodExplorer和phpMyAdmin两个图形化管理系统。

如果你不想部署上述的两个图形化管理系统,只需要运行以下指令即可:

  • GitHub版本:
sudo docker run --name uoj -dit -p 80:80 -p 3690:3690 --cap-add SYS_PTRACE uoj
  • DockerHub版本
sudo docker run --name uoj -dit -p 80:80 -p 3690:3690 -p 5678:5678 -p 6789:6789 --cap-add SYS_PTRACE universaloj/uoj-system:stable

接下来Docker容器将在后台运行,你可以在客户机浏览器输入localhost127.0.0.1来访问它。

在客户机终端使用下面的命令来关闭它:

sudo docker stop uoj

至此,UOJ相关部署工作已经基本完成。UOJ-System文件夹到此已完成使命,所有操作将于此文件夹无关

注意!从下面的操作开始,容器已经被创建完成。因此,终端也被分为客户机终端和容器终端,请区分好容器终端和客户机终端,以免发生不必要的错误!

部署图形化管理系统

下面就是部署指北中绝对没有的部分。

安装KodExplorer图形界面

在容器终端中依次输入以下指令创建并转到Kod文件夹:

mkdir /var/www/kod
cd /var/www/kod

然后在容器终端依次运行以下命令下载并解压Kod本体:

apt install wget
wget http://static.kodcloud.com/update/download/kodexplorer4.37.zip
unzip kodexplorer4.37.zip

然后在容器终端依次运行以下命令补全Kod运行先决条件:

apt install php5-curl
apt install php5-gd
chmod -Rf 777 /var/www/kod

接下来在内置的Apache2服务器建立服务配置:

在容器终端输入以下命令:

touch /etc/apache2/sites-available/001-kod.conf

执行以下命令进入vi编辑器并编辑001-kod.conf文件

vi /etc/apache2/sites-available/001-kod.conf

按下i键开始编辑,然后复制以下内容粘贴到编辑器中。


	# The ServerName directive sets the request scheme, hostname and port that
	# the server uses to identify itself. This is used when creating
	# redirection URLs. In the context of virtual hosts, the ServerName
	# specifies what hostname must appear in the request's Host: header to
	# match this virtual host. For the default virtual host (this file) this
	# value is not decisive as it is used as a last resort host regardless.
	# However, you must set it for any further virtual host explicitly.
	#ServerName www.example.com

	ServerAdmin admin
	DocumentRoot /var/www/kod

	# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
	# error, crit, alert, emerg.
	# It is also possible to configure the loglevel for particular
	# modules, e.g.
	#LogLevel info ssl:warn

	# For most configuration files from conf-available/, which are
	# enabled or disabled at a global level, it is possible to
	# include a line for only one particular virtual host. For example the
	# following line enables the CGI configuration for this host only
	# after it has been globally disabled with "a2disconf".
	#Include conf-available/serve-cgi-bin.conf


# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

如果您想修改Kod的部署端口,请将第一行中的5678修改成你需要的端口,前提是你在使用run命令的时候已经配置好了端口映射。

注意,复制的时候可能会带出多余内容,请酌情删除多余内容(主要是自动带上的版权声明)。

然后在容器终端使用vi浏览器编辑/etc/apache2/ports.conf文件:

vi /etc/apache2/ports.conf

Listen 80后面加入:

Listen 5678

然后在容器终端建立软链接:

ln -s /etc/apache2/sites-available/001-kod.conf /etc/apache2/sites-enabled

完成后,在客户机浏览器中使用127.0.0.1:5678localhost:5678来测试你的Kod系统。如果您能看到图形化管理界面,那么您的安装就成功了。

系统的管理员用户名admin,密码在刚登录的时候会让你设置。

图形化管理界面不是必须的,但是它会减小你接下来维护的难度。

安装phpMyAdmin图形化数据库管理系统

接下来的步骤您可以使用上一步部署的Kod系统,也可以使用命令行完成。下面的说明以Kod系统来讲解:

在这里下载phpMyAdmin数据库管理系统至客户机,也可以使用wget命令直接下载到容器中。

下载完成后,利用上一步安装的KOD系统将该压缩文件上传到容器中,并解压至/var/www/phpMyAdmin,确保该文件夹中有index.php这一文件。

或者你也可以使用客户机终端来复制文件:

docker cp 客户机文件或文件夹地址 容器名:容器中的地址

转到etc/apache2/sites-available文件夹,在该目录下创建文件002-phpmy.conf,并加入以下内容:


	# The ServerName directive sets the request scheme, hostname and port that
	# the server uses to identify itself. This is used when creating
	# redirection URLs. In the context of virtual hosts, the ServerName
	# specifies what hostname must appear in the request's Host: header to
	# match this virtual host. For the default virtual host (this file) this
	# value is not decisive as it is used as a last resort host regardless.
	# However, you must set it for any further virtual host explicitly.
	#ServerName www.example.com

	ServerAdmin [email protected]
	DocumentRoot /var/www/phpMyAdmin

	# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
	# error, crit, alert, emerg.
	# It is also possible to configure the loglevel for particular
	# modules, e.g.
	#LogLevel info ssl:warn

	ErrorLog ${APACHE_LOG_DIR}/phpMyAdmin_error.log
	CustomLog ${APACHE_LOG_DIR}/phpMyAdmin_access.log combined

	# For most configuration files from conf-available/, which are
	# enabled or disabled at a global level, it is possible to
	# include a line for only one particular virtual host. For example the
	# following line enables the CGI configuration for this host only
	# after it has been globally disabled with "a2disconf".
	#Include conf-available/serve-cgi-bin.conf


# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

如果您想修改部署端口,请将第一行中的6789修改成你需要的端口,前提是你在使用run命令的时候已经配置好了端口映射。

注意,复制的时候可能会带出多余内容,请酌情删除多余内容(主要是自动带上的版权声明)。

然后编辑/etc/apache2/ports.conf文件,在Listen 80后面加入:

Listen 6789

然后在容器终端建立链接:

ln -s /etc/apache2/sites-available/002-phpmy.conf /etc/apache2/sites-enabled

完成后,在客户机浏览器中使用127.0.0.1:6789localhost:6789来测试你的系统。如果您能看到图形化管理界面,那么您的安装就成功了。

管理UOJ容器

由于服务器安置在docker下,需要docker命令进行管理。

打开容器

docker start uoj

其中,uoj是你的容器名称。

进入容器终端

docker docker attach uoj

或者

docker exec -it uoj /bin/bash

关闭容器

sudo docker stop uoj

删除容器

慎重使用!操作不可逆!

sudo docker rm uoj

将容器导出为镜像

保存UOJ的服务器为”uoj_back”镜像:

sudo docker commit uoj uoj_back

一次典型的数据备份与恢复程序:

docker commit uoj uoj_back_20170101     # 例行备份
docker commit uoj uoj_back_20170201     # 例行备份
docker commit uoj uoj_back_20170301     # 例行备份

# 3月15日,黑恶势力破坏了uoj,uoj容器已经无用,必须恢复

sudo docker stop uoj
sudo docker rm uoj                      # 删除uoj容器
sudo docker run --name uoj -dit -p 80:80 -p 3690:3690 -p 5678:5678 -p 6789:6789 --cap-add SYS_PTRACE uoj_back_20170301
# 使用3月1日的备份创建新的容器

启动和关闭容器中的服务

Apache2

service apache2 start		#启动Apache2
service apache2 stop		#关闭Apache2
service apache2 restart		#重启Apache2

MySQL

service mysql start		#启动mysql
service mysql stop		#关闭mysql
service mysql restart		#重启mysql

更多内容

更多内容请参阅:

  • UOJ部署指北

  • UOJ官方文档

你可能感兴趣的:(OJ开发,UOJ部署)