学校里想要部署一套OJ,然后就选了UOJ。
但是由于服务器还要一段时间(永远)才能到,所以就先拿了一台电脑作为试验机进行内网部署测试。
非常感谢以下大佬:
- vfleaking 无私开放了UOJ的源码
- 阮行止 维护社区版本UOJ源码并且提供大量帮助
- 湘江一桥 维护社区版本UOJ源码并且提供大量帮助
- 其他提供帮助的人
这篇部署教程就是第一来帮助更多人,第二。。。帮自己在正式部署的时候不会乱了阵脚。。。
另外,引用了部分UOJ部署指北中的内容。
现在我已经是第四次对这篇博客进行修改了。不过不同于前三次,这一次进行了巨大的修改,主要是把里面的一些不正确的、过时的东西给修正了。
这篇文章刚刚被写出来的时候还是题主在高二时期,那时候对于Linux系统几乎没有什么理解,对终端、命令、Docker系统甚至是网站服务一无所知。不过即便是在那样的条件下,我还是坚持研究并成功积累了一些部署和开发的经验。
本着分享的原则,我写下了两年前的这篇博客,也是为了防止自己忘掉这些经历。
但是水平有限是硬伤。许多词汇并不专业,甚至错误连篇。
写下这篇补充前言的时候,题主已是一名软件工程学院的大一学生,已经积累了一部分Linux知识和网站搭建的能力,对这些东西的理解更深了。
翻出多年前的博客,我决定将它修改成正确的、对新手真正有帮助的博客。
本博客的面向人群是缺乏部署经验的新手开发者,对于高手而言可能内容比较冗杂,可以酌情跳过。如果您发现文档中的任何问题,请在下方评论区进行回复,谢谢。
另外,本博客为原创博客。您可以随意转载本博客,但是请务必附上题主AdemJensen的原始博客地址或者个人页面。如果被我发现抄袭行为的,一律进行举报,感谢您对原创作者的尊重。
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被设计的时候,出于安全考虑,网站服务器和数据库都被放置在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
锁定,否则数字是输不进去的。
另外,如未说明,下面的指令均是在客户机的终端中进行。当容器创建完毕后,终端将会分客户机终端和容器终端。
更新软件源以确保获取最新的docker。
apt update
然后更新机上的软件。这一步其实无所谓,而且比较花时间,可以跳过。
apt upgrade
下面部署沙盒系统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社区版现在比较厉害,有两种获取系统安装镜像的方式。
一种是从GitHub上抓取,这种方法可以保证你抓取到的是最新版的UOJ,但是需要运行install
脚本创建Docker镜像。
另一种是从DockerHub上抓取,这样抓取相对比较方便,但是版本跟不上最新的UOJ(而且密码找回功能可能有问题,需要手动修复),并且镜像安装出来的系统不支持Java代码评测。
可以登录这个地址下载安装源代码。
或者执行下面的指令获取源代码:
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.gz
和jdk-8u31-linux-x64.tar.gz
。
在2017-4-23之前的版本是在 UOJ-System
文件夹中。你应该能看到这个文件夹中有一个install
文件。
请注意,
UOJ-System/docker
文件夹中也有一个重名的文件,千万不要运行那个!
转到UOJ-System
文件夹,然后输入指令:
sudo bash ./install
安装脚本将会自动开始获取需要的内容并创建镜像。如果创建过程顺利的话,您将会看到Successfully built
字样。社区版的安装脚本会将创建出来的镜像自动命名为uoj
(官方原版需要使用后面脚本输出的哈希值)。
只需要运行下面的命令即可:
sudo docker pull universaloj/uoj-system:stable
sudo docker run --name uoj -dit -p 80:80 -p 3690:3690 -p 5678:5678 -p 6789:6789 --cap-add SYS_PTRACE uoj
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容器将在后台运行,你可以在客户机浏览器输入localhost
或127.0.0.1
来访问它。
在客户机终端使用下面的命令来关闭它:
sudo docker stop uoj
至此,UOJ相关部署工作已经基本完成。UOJ-System
文件夹到此已完成使命,所有操作将于此文件夹无关。
注意!从下面的操作开始,容器已经被创建完成。因此,终端也被分为客户机终端和容器终端,请区分好容器终端和客户机终端,以免发生不必要的错误!
下面就是部署指北中绝对没有的部分。
在容器终端中依次输入以下指令创建并转到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:5678
或localhost:5678
来测试你的Kod系统。如果您能看到图形化管理界面,那么您的安装就成功了。
系统的管理员用户名admin
,密码在刚登录的时候会让你设置。
图形化管理界面不是必须的,但是它会减小你接下来维护的难度。
接下来的步骤您可以使用上一步部署的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:6789
或localhost:6789
来测试你的系统。如果您能看到图形化管理界面,那么您的安装就成功了。
由于服务器安置在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日的备份创建新的容器
service apache2 start #启动Apache2
service apache2 stop #关闭Apache2
service apache2 restart #重启Apache2
service mysql start #启动mysql
service mysql stop #关闭mysql
service mysql restart #重启mysql
更多内容请参阅:
UOJ部署指北
UOJ官方文档