Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Don't merge] 容器化 hackergame 平台 #175

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,5 @@ RUN pip3 install --upgrade -r requirements.txt
# to avoid copying credentials inside container
# COPY ./ /opt/hackergame/

CMD ["/usr/local/bin/uwsgi", "--master", "--ini", "conf/uwsgi.ini", \
"--ini", "conf/uwsgi-apps/hackergame-docker.ini", \
"--set-placeholder", "appname=hackergame-docker"]
EXPOSE 2018
CMD ["docker/start.sh"]
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,17 @@
1. 其他配置文件:`cp conf/pgbouncer.ini /etc/pgbouncer/`, `systemctl restart pgbouncer`。
1. 配置反向代理的客户端 IP 透传:前置反向代理需使用 `X-Real-IP` 请求头传递客户端 IP,`/etc/nginx/sites-enabled/hackergame` 中需添加一行 `set_real_ip_from <reverse-proxy-ip>` 以信任来自 `reverse-proxy-ip` 的指示客户端 IP 的请求头,否则平台不能正确获取用户 IP。

另外我们提供 [docker compose 样例](./docker-compose.yml),但是实际部署不使用该容器版本。
### Docker compose

另外我们提供包括数据库与 nginx 等在内的 [docker compose 样例](./docker-compose.yml),但是**实际部署不使用该容器版本**。

与部署版本不同,该样例**默认开启了调试模式(环境变量 `DEBUG`),并且允许 hostname 为 localhost 等本地地址**。

1. 复制 `docker/.env.example` 到 `.env`:`cp docker/.env.example .env`。并修改其中的环境变量(为数据库设置密码)。
1. 执行 `docker compose up` 启动环境。
1. 执行 `docker exec -it hackergame ./manage.py migrate` 初始化数据库。
1. 执行 `docker exec -it hackergame ./manage.py collectstatic` 初始化 Static 目录。
1. 执行 `docker exec -it hackergame ./manage.py setup` 写入 Google 与 Microsoft app secret。

### uWSGI 运行模型

Expand Down
39 changes: 39 additions & 0 deletions conf/nginx-sites/hackergame-docker
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
server {
listen 80;
#server_name hack.lug.ustc.edu.cn;
server_name _;

charset utf-8;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
log_not_found off;

include /etc/nginx/mime.types;
default_type application/octet-stream;

access_log /var/log/nginx/hackergame.log;
error_log /var/log/nginx/hackergame.error.log;

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

location /media {
root /var/opt/hackergame;
add_header Content-Type application/octet-stream;
expires -1;
}
location /static {
root /var/opt/hackergame;
expires 1h;
}
location / {
uwsgi_pass hackergame:2018;
client_max_body_size 500M;
include /etc/nginx/uwsgi_params;
}
}
17 changes: 17 additions & 0 deletions conf/settings/docker.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
from .hackergame import *
import os

# Official domain and localhost for local test
ALLOWED_HOSTS = ["hack.lug.ustc.edu.cn", '.localhost', '127.0.0.1', '[::1]']
# For local test
DEBUG = os.environ.get('DEBUG', 'False') == 'True'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'hackergame',
'USER': 'hackergame',
'CONN_MAX_AGE': 0,
'ATOMIC_REQUESTS': True,
'HOST': 'pgbouncer',
'PORT': 5432,
'PASSWORD': os.environ.get('DB_PASSWORD', ''),
},
}
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache',
Expand Down
9 changes: 4 additions & 5 deletions conf/uwsgi-apps/hackergame-docker.ini
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
[uwsgi]
socket=unix:///run/uwsgi/app/hackergame-docker/socket
socket=:2018
chdir=/opt/hackergame
#plugin=python3,gevent_python3
module=frontend.wsgi:application
env=DJANGO_SETTINGS_MODULE=conf.settings.hackergame
env=PSYCOPG_WAIT_FUNC=wait_selector
master=true
#processes=16
gevent=1024
gevent-monkey-patch=true
vacuum=true
home=/usr/local
uid=www-data
gid=www-data
#home=/usr/local
#uid=www-data
#gid=www-data
stats=/run/uwsgi/app/hackergame-docker/stats.socket
harakiri=60
57 changes: 48 additions & 9 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,62 @@ services:
hackergame:
container_name: &name hackergame
hostname: *name
image: ghcr.io/ustclug/hackergame:latest
build: .
restart: always
environment:
- DJANGO_SETTINGS_MODULE=conf.settings.docker
- DB_PASSWORD=${DB_PASSWORD}
# 调试用
- DEBUG=True
volumes:
- .:/opt/hackergame/:ro
# 容器外使用 /run/uwsgi/app/hackergame-docker/socket 提供服务
# 需要提前将 /run/uwsgi/app/hackergame-docker/ 的 owner 修改为 www-data
# 参考 conf/nginx-sites/hackergame 的配置修改 nginx 配置
- /run/uwsgi/app/hackergame-docker/:/run/uwsgi/app/hackergame-docker/
# 存储静态网页与题目文件
- /var/opt/hackergame/:/var/opt/hackergame/
# 数据库,需要在容器外配置好 postgresql 和 pgbouncer
- /var/run/postgresql/:/var/run/postgresql/
- hackergame-static:/var/opt/hackergame/
# 很不幸,你可能还需要 bind 完整的题目目录进来(不然不方便导入)
depends_on:
- memcached
- pgbouncer
memcached:
container_name: memcached
container_name: hackergame-memcached
image: memcached
restart: always
postgresql:
container_name: hackergame-postgresql
image: postgres:15
restart: always
environment:
- POSTGRES_USER=hackergame
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB=hackergame
volumes:
- hackergame-postgresql:/var/lib/postgresql/data/
pgbouncer:
container_name: hackergame-pgbouncer
image: edoburu/pgbouncer:latest
restart: always
environment:
- DB_USER=hackergame
- DB_PASSWORD=${DB_PASSWORD}
- DB_HOST=postgresql
- POOL_MODE=transaction
# 坑: pg14+ 默认使用 scram-sha-256, 而 pgbouncer 默认是 md5
- AUTH_TYPE=scram-sha-256
depends_on:
- postgresql
nginx:
container_name: hackergame-nginx
image: nginx:1.25
restart: always
volumes:
- ./conf/nginx-sites/hackergame-docker:/etc/nginx/conf.d/default.conf:ro
- hackergame-static:/var/opt/hackergame/:ro
- nginx-log:/var/log/nginx/:rw
ports:
- 12345:80
depends_on:
- hackergame

volumes:
hackergame-static:
nginx-log:
hackergame-postgresql:
1 change: 1 addition & 0 deletions docker/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DB_PASSWORD=youshouldmodifythis
17 changes: 17 additions & 0 deletions docker/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/sh -e

# Set permission for /run/uwsgi/app/hackergame-docker/
mkdir -p /run/uwsgi/app/hackergame-docker/
chown www-data:www-data /run/uwsgi/app/hackergame-docker/

echo "Note that /opt/hackergame/ shall be readable by uwsgi (www-data in container)."
echo "You could set it to be readable by everyone: chmod -R a+rX hackergame/"

echo "If this is your first time to run this container, you should run:"
echo " docker exec -it hackergame ./manage.py migrate"
echo " docker exec -it hackergame ./manage.py collectstatic"

# Start uwsgi
exec /usr/local/bin/uwsgi --master --ini conf/uwsgi.ini \
--ini conf/uwsgi-apps/hackergame-docker.ini \
--set-placeholder appname=hackergame-docker
Loading