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/dmoj
From 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/initialize
Next, 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.env
Then, 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 build
Start up the site, so you can perform the initial migrations and generate the static files:
$ docker compose up -d site db redis celery
You will need to generate the schema for the database, since it is currently empty:
$ ./scripts/migrate
You will also need to generate the static files:
$ ./scripts/copy_static
Finally, 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 demo
Keep 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 createsuperuser
To start everything:
$ docker compose up -d
To stop everything:
$ docker compose down
The 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/migrate
If your static files ever change, you will need to rebuild them:
$ ./scripts/copy_static
Updating 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 wsevent
If 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 wsevent
The 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 wsevent
You 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