From b1793d29a2a930080c437d65ad9540d82140e74d Mon Sep 17 00:00:00 2001 From: virusdefender Date: Sun, 11 Jun 2017 01:20:05 +0800 Subject: [PATCH 1/6] new deploy --- build.sh | 1 + dockerfiles/judger/Dockerfile | 23 +++++-------- dockerfiles/oj_web_server/Dockerfile | 22 +++++------- dockerfiles/oj_web_server/gunicorn.conf | 12 ------- dockerfiles/oj_web_server/oj.example.conf | 18 ---------- dockerfiles/oj_web_server/run.sh | 16 +++++++-- dockerfiles/oj_web_server/sources.list | 8 ----- dockerfiles/oj_web_server/supervisord.conf | 39 ++++++++++++++++++++-- dockerfiles/oj_web_server/task_queue.conf | 12 ------- oj/server_settings.py | 12 +++---- oj/settings.py | 16 ++------- tools/create_db.py | 26 ++++----------- tools/release_static.py | 2 +- utils/management/commands/initadmin.py | 35 ++++--------------- 14 files changed, 90 insertions(+), 152 deletions(-) create mode 100755 build.sh delete mode 100644 dockerfiles/oj_web_server/gunicorn.conf delete mode 100644 dockerfiles/oj_web_server/oj.example.conf delete mode 100644 dockerfiles/oj_web_server/sources.list delete mode 100644 dockerfiles/oj_web_server/task_queue.conf diff --git a/build.sh b/build.sh new file mode 100755 index 00000000..d9903816 --- /dev/null +++ b/build.sh @@ -0,0 +1 @@ +docker build -t registry.cn-hangzhou.aliyuncs.com/qduoj/oj_web_server -f dockerfiles/oj_web_server/Dockerfile . diff --git a/dockerfiles/judger/Dockerfile b/dockerfiles/judger/Dockerfile index 3c01c3a5..055a7b5e 100644 --- a/dockerfiles/judger/Dockerfile +++ b/dockerfiles/judger/Dockerfile @@ -1,20 +1,15 @@ -FROM ubuntu:14.04 +FROM ubuntu:16.04 ENV DEBIAN_FRONTEND noninteractive -RUN rm /etc/apt/sources.list -COPY sources.list /etc/apt/ -RUN apt-get update -RUN apt-get -y install software-properties-common python-software-properties python python-dev gcc g++ git libtool python-pip libseccomp-dev -RUN add-apt-repository -y ppa:webupd8team/java -RUN echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections -RUN echo debconf shared/accepted-oracle-license-v1-1 seen true | sudo debconf-set-selections -RUN apt-get update -RUN apt-get install -y oracle-java7-installer -RUN cd /tmp && git clone https://github.com/QingdaoU/Judger && cd Judger && python setup.py install +RUN apt-get update && apt-get -y install software-properties-common python-software-properties python python-dev gcc g++ git libtool python-pip libseccomp-dev +RUN add-apt-repository -y ppa:webupd8team/java && echo debconf shared/accepted-oracle-license-v1-1 select true | debconf-set-selections && echo debconf shared/accepted-oracle-license-v1-1 seen true | debconf-set-selections +RUN apt-get update && apt-get install -y oracle-java8-installer +RUN cd /tmp && git clone -b master https://github.com/QingdaoU/Judger && cd Judger && python setup.py install RUN mkdir -p /var/judger/run/ && mkdir /var/judger/test_case/ && mkdir /var/judger/code/ RUN chmod -R 777 /var/judger/run/ -COPY policy /var/judger/run/ -COPY supervisord.conf /etc +COPY dockerfiles/judger/policy /var/judger/run/ +COPY dockerfiles/judger/supervisord.conf /etc RUN pip install supervisor +ADD . /var/judger/code WORKDIR /var/judger/code/judge/ EXPOSE 8080 -CMD bash /var/judger/code/dockerfiles/judger/run.sh \ No newline at end of file +CMD bash /var/judger/code/dockerfiles/judger/run.sh diff --git a/dockerfiles/oj_web_server/Dockerfile b/dockerfiles/oj_web_server/Dockerfile index def778d6..0fc78913 100644 --- a/dockerfiles/oj_web_server/Dockerfile +++ b/dockerfiles/oj_web_server/Dockerfile @@ -1,15 +1,11 @@ -FROM python:2.7 +FROM ubuntu:16.04 ENV PYTHONBUFFERED 1 -RUN mkdir -p /code/log /code/test_case /code/upload -WORKDIR /code -ADD requirements.txt /code/ -RUN pip install -i http://pypi.douban.com/simple -r requirements.txt --trusted-host pypi.douban.com -RUN rm /etc/apt/sources.list -ADD sources.list /etc/apt/ +RUN apt-get update && apt-get install -y nginx python-pip libmysqlclient-dev curl nodejs RUN curl -sL https://deb.nodesource.com/setup | bash - -RUN apt-get -y install nodejs -ADD gunicorn.conf /etc -ADD supervisord.conf /etc -ADD task_queue.conf /etc -EXPOSE 8080 -CMD bash /code/dockerfiles/oj_web_server/run.sh \ No newline at end of file +RUN apt-get install nodejs +ADD . /code +WORKDIR /code +RUN pip install -i https://pypi.douban.com/simple -r dockerfiles/oj_web_server/requirements.txt +RUN python tools/release_static.py +EXPOSE 80 +CMD bash /code/dockerfiles/oj_web_server/run.sh diff --git a/dockerfiles/oj_web_server/gunicorn.conf b/dockerfiles/oj_web_server/gunicorn.conf deleted file mode 100644 index 18dbab32..00000000 --- a/dockerfiles/oj_web_server/gunicorn.conf +++ /dev/null @@ -1,12 +0,0 @@ -[program:gunicorn] -command=gunicorn oj.wsgi:application -b 0.0.0.0:8080 --reload -directory=/code/ -user=nobody -numprocs=1 -stdout_logfile=/code/log/gunicorn.log -stderr_logfile=/code/log/gunicorn.log -autostart=true -autorestart=true -startsecs=5 -stopwaitsecs = 5 -killasgroup=true \ No newline at end of file diff --git a/dockerfiles/oj_web_server/oj.example.conf b/dockerfiles/oj_web_server/oj.example.conf deleted file mode 100644 index 30fa3603..00000000 --- a/dockerfiles/oj_web_server/oj.example.conf +++ /dev/null @@ -1,18 +0,0 @@ -server { - listen 80 default_server; - server_name _; - location /static/upload { - expires max; - alias /home/upload; - } - location /static { - etag off; - expires max; - alias /home/OnlineJudge/static/release; - } - location / { - client_max_body_size 100m; - proxy_pass http://oj_web_server:8080; - proxy_set_header Host $host; - } -} diff --git a/dockerfiles/oj_web_server/run.sh b/dockerfiles/oj_web_server/run.sh index 04b6d695..b0c0b30c 100644 --- a/dockerfiles/oj_web_server/run.sh +++ b/dockerfiles/oj_web_server/run.sh @@ -4,7 +4,17 @@ if [ ! -f "/code/oj/custom_settings.py" ]; then echo "SECRET_KEY=\"`cat /dev/urandom | head -1 | md5sum | head -c 32`\"" >> /code/oj/custom_settings.py fi find /code -name "*.pyc" -delete -python -m compileall /code +# python -m compileall /code chown -R nobody:nogroup /code/log /code/test_case /code/upload -echo "Waiting MySQL and Redis to start" -exec supervisord \ No newline at end of file +cd /code +n=0 +until [ $n -ge 5 ] +do + python tools/create_db.py && + python manage.py migrate --no-input && + python manage.py migrate --database=submission --no-input && + python manage.py initadmin && break + n=$(($n+1)) + sleep 8 +done +exec supervisord -c /code/dockerfiles/oj_web_server/supervisord.conf diff --git a/dockerfiles/oj_web_server/sources.list b/dockerfiles/oj_web_server/sources.list deleted file mode 100644 index 67caf139..00000000 --- a/dockerfiles/oj_web_server/sources.list +++ /dev/null @@ -1,8 +0,0 @@ -deb http://mirrors.aliyun.com/debian wheezy main contrib non-free -deb-src http://mirrors.aliyun.com/debian wheezy main contrib non-free - -deb http://mirrors.aliyun.com/debian wheezy-updates main contrib non-free -deb-src http://mirrors.aliyun.com/debian wheezy-updates main contrib non-free - -deb http://mirrors.aliyun.com/debian-security wheezy/updates main contrib non-free -deb-src http://mirrors.aliyun.com/debian-security wheezy/updates main contrib non-free \ No newline at end of file diff --git a/dockerfiles/oj_web_server/supervisord.conf b/dockerfiles/oj_web_server/supervisord.conf index 4026c19e..fa0ee039 100644 --- a/dockerfiles/oj_web_server/supervisord.conf +++ b/dockerfiles/oj_web_server/supervisord.conf @@ -5,11 +5,44 @@ logfile_backups=10 loglevel=info pidfile=/code/log/supervisord.pid nodaemon=true -user=nobody childlogdir=/code/log/ [supervisorctl] serverurl=unix:///tmp/supervisor.sock -[include] -files=gunicorn.conf task_queue.conf \ No newline at end of file +[program:gunicorn] +command=gunicorn oj.wsgi:application --user nobody -b 127.0.0.1:8080 --reload +directory=/code/ +numprocs=1 +stdout_logfile=/code/log/gunicorn.log +stderr_logfile=/code/log/gunicorn.log +autostart=true +autorestart=true +startsecs=5 +stopwaitsecs = 5 +killasgroup=true + +[program:task_queue] +command=celery -A oj worker -l warning +directory=/code/ +user=nobody +numprocs=1 +stdout_logfile=/code/log/task_queue.log +stderr_logfile=/code/log/task_queue.log +autostart=true +autorestart=true +startsecs=5 +stopwaitsecs = 5 +killasgroup=true + +[program:nginx] +command=nginx -c /code/dockerfiles/oj_web_server/oj.conf +directory=/code/ +numprocs=1 +stdout_logfile=/code/log/nginx.log +stderr_logfile=/code/log/nginx.log +autostart=true +autorestart=true +startsecs=5 +stopwaitsecs = 5 +killasgroup=true diff --git a/dockerfiles/oj_web_server/task_queue.conf b/dockerfiles/oj_web_server/task_queue.conf deleted file mode 100644 index dd51bebc..00000000 --- a/dockerfiles/oj_web_server/task_queue.conf +++ /dev/null @@ -1,12 +0,0 @@ -[program:task_queue] -command=celery -A oj worker --autoscale=30,4 -l DEBUG -directory=/code/ -user=nobody -numprocs=1 -stdout_logfile=/code/log/task_queue.log -stderr_logfile=/code/log/task_queue.log -autostart=true -autorestart=true -startsecs=5 -stopwaitsecs = 5 -killasgroup=true \ No newline at end of file diff --git a/oj/server_settings.py b/oj/server_settings.py index 9ec8dcfb..e54635b4 100644 --- a/oj/server_settings.py +++ b/oj/server_settings.py @@ -7,8 +7,8 @@ DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': "oj", - 'CONN_MAX_AGE': 0.1, - 'HOST': os.environ["MYSQL_PORT_3306_TCP_ADDR"], + 'CONN_MAX_AGE': 10, + 'HOST': "oj_mysql", 'PORT': 3306, 'USER': os.environ["MYSQL_ENV_MYSQL_USER"], 'PASSWORD': os.environ["MYSQL_ENV_MYSQL_ROOT_PASSWORD"] @@ -16,8 +16,8 @@ DATABASES = { 'submission': { 'NAME': 'oj_submission', 'ENGINE': 'django.db.backends.mysql', - 'CONN_MAX_AGE': 0.1, - 'HOST': os.environ["MYSQL_PORT_3306_TCP_ADDR"], + 'CONN_MAX_AGE': 10, + 'HOST': "oj_mysql", 'PORT': 3306, 'USER': os.environ["MYSQL_ENV_MYSQL_USER"], 'PASSWORD': os.environ["MYSQL_ENV_MYSQL_ROOT_PASSWORD"] @@ -25,13 +25,13 @@ DATABASES = { } REDIS_CACHE = { - "host": os.environ["REDIS_PORT_6379_TCP_ADDR"], + "host": "oj_redis", "port": 6379, "db": 1 } REDIS_QUEUE = { - "host": os.environ["REDIS_PORT_6379_TCP_ADDR"], + "host": "oj_redis", "port": 6379, "db": 2 } diff --git a/oj/settings.py b/oj/settings.py index 847c19e5..d1b5276d 100644 --- a/oj/settings.py +++ b/oj/settings.py @@ -124,18 +124,6 @@ LOGGING = { # 日志格式 }, 'handlers': { - 'django_error': { - 'level': 'DEBUG', - 'class': 'logging.handlers.RotatingFileHandler', - 'filename': LOG_PATH + 'django.log', - 'formatter': 'standard' - }, - 'app_info': { - 'level': 'DEBUG', - 'class': 'logging.handlers.RotatingFileHandler', - 'filename': LOG_PATH + 'app_info.log', - 'formatter': 'standard' - }, 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', @@ -144,12 +132,12 @@ LOGGING = { }, 'loggers': { 'app_info': { - 'handlers': ['app_info', "console"], + 'handlers': ["console"], 'level': 'DEBUG', 'propagate': True }, 'django.request': { - 'handlers': ['django_error', 'console'], + 'handlers': ['console'], 'level': 'DEBUG', 'propagate': True, }, diff --git a/tools/create_db.py b/tools/create_db.py index 30e9a0ae..473eed4b 100644 --- a/tools/create_db.py +++ b/tools/create_db.py @@ -2,22 +2,10 @@ import os import time import MySQLdb -""" -docker-compose启动的时候是并行启动的,可能执行本脚本的时候MySQL还没启动完 -""" -i = 3 -while i: - try: - conn = MySQLdb.connect(host=os.environ["MYSQL_PORT_3306_TCP_ADDR"], - user=os.environ["MYSQL_ENV_MYSQL_USER"], - passwd=os.environ["MYSQL_ENV_MYSQL_ROOT_PASSWORD"]) - conn.cursor().execute("create database if not exists oj default character set utf8;") - conn.cursor().execute("create database if not exists oj_submission default character set utf8;") - print "Create database successfully" - exit(0) - except Exception as e: - print "Failed to create database, error: " + str(e) + ", will retry in 3 seconds" - i -= 1 - time.sleep(3) -print "Failed to create database" -exit(1) + +conn = MySQLdb.connect(host="oj_mysql", + user=os.environ["MYSQL_ENV_MYSQL_USER"], + passwd=os.environ["MYSQL_ENV_MYSQL_ROOT_PASSWORD"]) +conn.cursor().execute("create database if not exists oj default character set utf8;") +conn.cursor().execute("create database if not exists oj_submission default character set utf8;") +print "Create database successfully" diff --git a/tools/release_static.py b/tools/release_static.py index 2ab87e5d..adb4a02a 100644 --- a/tools/release_static.py +++ b/tools/release_static.py @@ -11,7 +11,7 @@ static_src_path = "static/src/" static_release_path = "static/release/" print "Begin to compress js" -if os.system("node static/src/js/r.js -o static/src/js/build.js"): +if os.system("nodejs static/src/js/r.js -o static/src/js/build.js"): print "Failed to compress js, exit" exit() diff --git a/utils/management/commands/initadmin.py b/utils/management/commands/initadmin.py index d23e7f18..4aaccb52 100644 --- a/utils/management/commands/initadmin.py +++ b/utils/management/commands/initadmin.py @@ -1,36 +1,13 @@ # coding=utf-8 from django.core.management.base import BaseCommand from account.models import User, SUPER_ADMIN, UserProfile -from utils.shortcuts import rand_str class Command(BaseCommand): def handle(self, *args, **options): - try: - admin = User.objects.get(username="root") - if admin.admin_type == SUPER_ADMIN: - self.stdout.write(self.style.WARNING("Super admin user 'root' already exists, " - "would you like to reset it's password?\n" - "Input yes to confirm: ")) - if raw_input() == "yes": - rand_password = rand_str(length=6) - admin.set_password(rand_password) - admin.save() - self.stdout.write(self.style.SUCCESS("Successfully created super admin user password.\n" - "Username: root\nPassword: %s\n" - "Remember to change password and turn on two factors auth " - "after installation." % rand_password)) - else: - self.stdout.write(self.style.SUCCESS("Nothing happened")) - else: - self.stdout.write(self.style.ERROR("User 'root' is not super admin.")) - except User.DoesNotExist: - user = User.objects.create(username="root", real_name="root", email="root@oj.com", admin_type=SUPER_ADMIN) - rand_password = rand_str(length=6) - user.set_password(rand_password) - user.save() - UserProfile.objects.create(user=user) - self.stdout.write(self.style.SUCCESS("Successfully created super admin user.\n" - "Username: root\nPassword: %s\n" - "Remember to change password and turn on two factors auth " - "after installation." % rand_password)) + if User.objects.exists(): + return + user = User.objects.create(username="root", real_name="root", email="root@oj.com", admin_type=SUPER_ADMIN) + user.set_password("password@root") + user.save() + UserProfile.objects.create(user=user) From 4054dfa41c32a62acb847add1e3074326a7d6a88 Mon Sep 17 00:00:00 2001 From: virusdefender Date: Wed, 14 Jun 2017 15:59:22 +0800 Subject: [PATCH 2/6] update deploy --- .gitignore | 1 - dockerfiles/oj_web_server/Dockerfile | 1 - dockerfiles/oj_web_server/oj.conf | 56 ++++++++++++++++++++ dockerfiles/oj_web_server/requirements.txt | 2 +- judge_dispatcher/serializers.py | 4 +- template/src/admin/judges/judges.html | 8 +-- template/src/oj/problem/_submit_problem.html | 8 +-- template/src/utils/help.html | 6 +-- 8 files changed, 70 insertions(+), 16 deletions(-) create mode 100644 dockerfiles/oj_web_server/oj.conf diff --git a/.gitignore b/.gitignore index 011edeca..3c7f32b3 100644 --- a/.gitignore +++ b/.gitignore @@ -68,4 +68,3 @@ custom_settings.py docker-compose.yml *.zip rsyncd.passwd -oj.conf \ No newline at end of file diff --git a/dockerfiles/oj_web_server/Dockerfile b/dockerfiles/oj_web_server/Dockerfile index 0fc78913..56d191db 100644 --- a/dockerfiles/oj_web_server/Dockerfile +++ b/dockerfiles/oj_web_server/Dockerfile @@ -7,5 +7,4 @@ ADD . /code WORKDIR /code RUN pip install -i https://pypi.douban.com/simple -r dockerfiles/oj_web_server/requirements.txt RUN python tools/release_static.py -EXPOSE 80 CMD bash /code/dockerfiles/oj_web_server/run.sh diff --git a/dockerfiles/oj_web_server/oj.conf b/dockerfiles/oj_web_server/oj.conf new file mode 100644 index 00000000..2eb08e84 --- /dev/null +++ b/dockerfiles/oj_web_server/oj.conf @@ -0,0 +1,56 @@ +worker_processes 1; +user www-data; +error_log /dev/stderr warn; +daemon off; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + # access_log /dev/stdout main; + access_log off; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + gzip on; + gzip_types application/javascript text/css; + + upstream backend { + server 127.0.0.1:8080; + keepalive 32; + } + + server { + listen 80 default_server; + server_name _; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $http_host; + client_max_body_size 200M; + + location /static/upload { + expires max; + alias /code/upload; + } + location /static { + etag off; + expires max; + alias /code/static/release; + } + location / { + proxy_pass http://backend; + proxy_set_header Host $host; + } + } +} + diff --git a/dockerfiles/oj_web_server/requirements.txt b/dockerfiles/oj_web_server/requirements.txt index 0abcfcf3..3b505741 100644 --- a/dockerfiles/oj_web_server/requirements.txt +++ b/dockerfiles/oj_web_server/requirements.txt @@ -2,7 +2,7 @@ django==1.9.6 MySQL-python redis django-redis-sessions -djangorestframework +djangorestframework==3.2.5 django-rest-swagger gunicorn coverage diff --git a/judge_dispatcher/serializers.py b/judge_dispatcher/serializers.py index 4328eee9..5efa79cd 100644 --- a/judge_dispatcher/serializers.py +++ b/judge_dispatcher/serializers.py @@ -6,7 +6,7 @@ from .models import JudgeServer class CreateJudgesSerializer(serializers.Serializer): name = serializers.CharField(max_length=30) - ip = serializers.IPAddressField() + ip = serializers.CharField(max_length=128) port = serializers.IntegerField() # 这个服务器最大可能运行的判题实例数量 max_instance_number = serializers.IntegerField() @@ -16,7 +16,7 @@ class CreateJudgesSerializer(serializers.Serializer): class EditJudgesSerializer(serializers.Serializer): id = serializers.IntegerField() name = serializers.CharField(max_length=30) - ip = serializers.IPAddressField() + ip = serializers.CharField(max_length=128) port = serializers.IntegerField() # 这个服务器最大可能运行的判题实例数量 max_instance_number = serializers.IntegerField() diff --git a/template/src/admin/judges/judges.html b/template/src/admin/judges/judges.html index 82d8f84e..364089af 100644 --- a/template/src/admin/judges/judges.html +++ b/template/src/admin/judges/judges.html @@ -47,8 +47,8 @@
- - + +
@@ -100,8 +100,8 @@
- - + +
diff --git a/template/src/oj/problem/_submit_problem.html b/template/src/oj/problem/_submit_problem.html index f21f45df..079ffb76 100644 --- a/template/src/oj/problem/_submit_problem.html +++ b/template/src/oj/problem/_submit_problem.html @@ -2,13 +2,13 @@
@@ -22,4 +22,4 @@ 提交代码 - \ No newline at end of file + diff --git a/template/src/utils/help.html b/template/src/utils/help.html index 3c9a1539..5ed1ed02 100644 --- a/template/src/utils/help.html +++ b/template/src/utils/help.html @@ -25,11 +25,11 @@

编译参数