This repository contains the Docker files to run the VNOJ.
Based on dmoj-docker.
First, Docker and Docker Compose must be installed. Installation instructions can be found on their respective websites.
Clone the repository:
$ git clone --recursive https://github.com/VNOI-Admin/vnoj-docker.git
$ cd vnoj-docker/dmojFrom now on, it is assumed you are in the dmoj directory.
Initialize the setup by moving the configuration files into the submodule and creating the necessary directories:
$ ./scripts/initializeNext, configure the environment variables in the files in dmoj/environment/. Create the files from the examples:
$ cp environment/mysql-admin.env.example environment/mysql-admin.env
$ cp environment/mysql.env.example environment/mysql.env
$ cp environment/site.env.example environment/site.envThen, set the MYSQL passwords in mysql.env and mysql-admin.env, and the host and secret key in site.env. Also, configure the server_name directive in dmoj/nginx/conf.d/nginx.conf.
Next, build the images:
$ docker compose buildStart up the site, so you can perform the initial migrations and generate the static files:
$ docker compose up -d site db redis celeryYou will need to generate the schema for the database, since it is currently empty:
$ ./scripts/migrateYou will also need to generate the static files:
$ ./scripts/copy_staticFinally, the VNOJ comes with fixtures so that the initial install is not blank. They can be loaded with the following commands:
$ ./scripts/manage.py loaddata navbar
$ ./scripts/manage.py loaddata language_small
$ ./scripts/manage.py loaddata demoKeep in mind that the demo fixture creates a superuser account with a username and password of admin. You should change the user's password or remove the user entirely.
You can also create a superuser account for yourself:
$ ./scripts/manage.py createsuperuserTo start everything:
$ docker compose up -dTo stop everything:
$ docker compose downThe judge server is not included in this Docker setup. Please refer to Setting up a Judge.
The bridge instance is included in this Docker setup and should be running once you start everything.
As the VNOJ site is a Django app, you may need to migrate whenever you update. Assuming the site container is running, running the following command should suffice:
$ ./scripts/migrateIf your static files ever change, you will need to rebuild them:
$ ./scripts/copy_staticUpdating various sections of the site requires different images to be rebuilt.
If any prerequisites were modified, you will need to rebuild most of the images:
$ docker compose up -d --build base site celery bridged wseventIf the static files are modified, read the section on Managing Static Files.
If only the source code is modified, a restart is sufficient:
$ docker compose restart site celery bridged wseventThe docker-compose.yml configures Nginx to publish to port 80. If you have another Nginx instance on your host machine, you may want to change the port and proxy pass instead.
For example, a possible Nginx configuration file on your host machine would be:
server {
listen 80;
listen [::]:80;
add_header X-UA-Compatible "IE=Edge,chrome=1";
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
location / {
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:10080/;
}
}
In this case, the port that the Nginx instance in the Docker container is published to would need to be modified to 10080.
By default, all services (site, bridged, wsevent, db, celery, redis, etc.) run in the same machine. However, it is not ideal for handling a large number of users. In this case, you need to distribute the services to multiple servers. A typical setup would be:
- One central server for nginx, db, redis, bridged, and wsevent
- Multiple workers, each will run nginx, site, and celery
You need to configure dmoj/nginx/conf.d/nginx.conf to distribute traffic to workers. Refer to Nginx docs for how to do it.
A sample configuration:
upstream site {
ip_hash;
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
server {
listen 80;
listen [::]:80;
location / {
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://site/;
}
location /event/ {
proxy_pass http://wsevent:15100/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
location /channels/ {
proxy_read_timeout 120;
proxy_pass http://wsevent:15102/;
}
}
Uncomment ports blocks in dmoj/docker-compose.yml. You also need to open these ports for workers to connect to:
- db: 3306
- redis: 6379
- bridged: 9998 9999
- wsevent: 15100 15101 15102
Now, let's start the services:
docker compose up -d nginx db redis bridged wseventYou need to configure dmoj/environment/site.env and dmoj/environment/mysql.env to point to the central server.
docker compose up -d nginx site celery