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

Add Dockerfile and CI workflows building Docker images on new releases #12

Merged
merged 14 commits into from
Apr 20, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
41 changes: 41 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# /rst/source/sections/modules.rst
/build/
/dist/
# /test_report.html
# /test_report/
# /test_log.txt
# /test_screenshots.tar.gz
/.coverage
/cover/
**/*.egg
**/*.egg-info
**/*.pid
**/.DS_Store
**/*.pyc
**/__pycache__/
**/*.kdev*
**/*~
/.tox/
/.pytest_cache/
/.eggs/
**/*.swp
/deployment/
/venv*/
/.idea/

# docker specific

/Dockerfile*
/docker*
!docker-entrypoint.sh
/.dockerignore
/.git
/.gitignore
/.github
/extra/
/test*
/*.rst
/rst/

/docker/
/rst/
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
twisted/plugins/dropin.cache
config/supervisord.conf
config/supervisord-conf-vars.conf
config/logging.json
51 changes: 51 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
FROM python:3.7 as build

ENV PYTHONUNBUFFERED 1

RUN useradd -m oioioi \
&& mkdir -p /sio2/sioworkers \
&& chown -R oioioi:oioioi /sio2

USER oioioi
WORKDIR /sio2

RUN pip install --user virtualenv \
&& /home/oioioi/.local/bin/virtualenv -p python3.7 venv

COPY --chown=oioioi:oioioi setup.py setup.cfg requirements_py3.txt /sio2/sioworkers/
COPY --chown=oioioi:oioioi sio /sio2/sioworkers/sio
COPY --chown=oioioi:oioioi twisted /sio2/sioworkers/twisted

WORKDIR /sio2/sioworkers

RUN . /sio2/venv/bin/activate \
&& pip install -r requirements_py3.txt \
&& python setup.py install

FROM python:3.7 AS production

ENV PYTHONUNBUFFERED 1

RUN useradd -m oioioi \
&& mkdir -p /sio2/sioworkers \
&& chown -R oioioi:oioioi /sio2

COPY --from=build --chown=oioioi:oioioi /sio2/venv /sio2/venv

ENV PATH="/sio2/venv/bin:$PATH"

COPY --chown=oioioi:oioioi config/supervisord.conf.example /sio2/sioworkers/config/supervisord.conf
COPY --chown=oioioi:oioioi config/supervisord-conf-vars.conf.docker /sio2/sioworkers/config/supervisord-conf-vars.conf
COPY --chown=oioioi:oioioi config/logging.json.example /sio2/sioworkers/config/logging.json
COPY --chown=oioioi:oioioi supervisor.sh /sio2/sioworkers

COPY --chown=oioioi:oioioi docker-entrypoint.sh /sio2

USER oioioi
WORKDIR /sio2/sioworkers

ENV SIOWORKERSD_HOST="web"

ENTRYPOINT [ "/sio2/docker-entrypoint.sh" ]

CMD [ "/sio2/sioworkers/supervisor.sh", "startfg" ]
109 changes: 90 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,98 @@
# INSTALLATION
# Installation

### for python 2 installation ###
pip install -r requirements.txt
## Python 2
LiquidPL marked this conversation as resolved.
Show resolved Hide resolved

python setup.py install
```
$ pip install -r requirements.txt
$ python setup.py install
```

### for python 3 installation ###
pip install -r requirements_py3.txt
## Python 3

python setup.py install
```
$ pip install -r requirements_py3.txt
$ python setup.py install
```

# TESTS
# Tests

### to run all tests ###
`tox`
in main directory
All commands are executed in the main directory.

### to run twisted tests (python2) ###
run:
trial sio.sioworkersd.twisted_t
in the directory of installation
## All tests

### to run twisted tests (python3) ###
run:
trial sio/sioworkersd/twisted_t
in the directory of installation
```
$ tox
```

## Twisted (Python 2)

```
$ trial sio.sioworkersd.twisted_t
```

## Twisted (Python 3)
```
$ trial sio/sioworkers/twisted_t
```

# Docker

An official Docker image for sioworkers is available at (TODO: update this when the image location is decided).

```
$ docker run --rm \
--network=sio2-network \
--cap-add=ALL \
--privileged \
-e "SIOWORKERSD_HOST=oioioi" \
-e "WORKER_ALLOW_RUN_CPU_EXEC=true" \
-e "WORKER_CONCURRENCY=1" \
-e "WORKER_RAM=1024" \
--memory="1152m" \
--cpus=2.0 \
<TODO: container tag here>
```

Notes:
* `--privileged` is only needed if Sio2Jail is used for judging submissions (ie. `WORKER_ALLOW_RUN_CPU_EXEC` is set to `true`),
* You can limit the memory/CPUs available to the container how you usually would in the container runtime of your choice,
the container will determine how many workers it should expose to OIOIOI based on that.
* You can also manually override the amount of available workers/memory by specifying the `WORKER_CONCURRENCY` and `WORKER_RAM` (in MiB) environment variables.
* 128 MiB is reserved for processes in the container other than the submission being judged. That is, if you want
the maximum memory available to a judged program to be 1024 MiB, limit the container's memory to
128 MiB + (number of workers) * 1024 MiB.

Equivalent Docker Compose configuration:

```yaml
version: '3.8'

...

worker:
image: <TODO: container tag here>
deploy:
resources:
limits:
cpus: '2'
memory: 1152m
cap_add:
- ALL
privileged: true
environment:
SIOWORKERSD_HOST: 'web'
WORKER_ALLOW_RUN_CPU_EXEC: 'true'
# these *will* override any automatic detection of available
# memory/cpu cores based on container limits!
WORKER_CONCURRENCY: '1'
WORKER_RAM: '1024'
```

## Environment variables

The container exposes two environment variables, from which only `SIOWORKERSD_HOST` is required.

* `SIOWORKERSD_HOST` - name of the host on which the `sioworkersd` service is available (usually the same as the main OIOIOI instance)
* `WORKER_ALLOW_RUN_CPU_EXEC` - marks this worker as suitable for judging directly on the CPU (without any isolation like Sio2Jail).
This is used in some contest types (for instance, ACM style contests), however it isn't needed when running the regular OI style
contests.
38 changes: 38 additions & 0 deletions config/supervisord-conf-vars.conf.docker
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/bash

export WORKER_USER="$(id -u -n)"
export WORKER_HOME="/sio2/sioworkers"

export WORKER_LOGCONFIG="${WORKER_HOME}/config/logging.json"

# Cache cleaner config
export FILETRACKER_CACHE_CLEANER_ENABLED="true"
export CACHE_SIZE="10G"
export SCAN_INTERVAL="1h"
export CLEAN_LEVEL="50" # in percents

# Workers config
export WORKER_ENABLED="true"

# Set worker concurrency parameters
if [ ! -f /sys/fs/cgroup/cpu.max ] || [ $(cat /sys/fs/cgroup/cpu.max | cut -d \ -f 1) = "max" ] ; then
WORKERS_TOTAL=$(($(nproc) * 3/2))
else
WORKERS_TOTAL=$(cat /sys/fs/cgroup/cpu.max | awk '{print int($1 / $2)}')
fi

if [ ! -f /sys/fs/cgroup/memory.max ] || [ $(cat /sys/fs/cgroup/memory.max) = "max" ]; then
MEM_TOTAL=$(grep MemTotal /proc/meminfo | awk '{print int($2 / 1024)}') # in MiB
else
MEM_TOTAL=$(cat /sys/fs/cgroup/memory.max | awk '{print int($1 / 1048576)}') # in MiB
fi
# Set how much memory we should reserve for OS
OS_MEMORY=128 # in MiB

if [ -z ${WORKER_RAM+x} ]; then
export WORKER_RAM=$(($MEM_TOTAL - $OS_MEMORY))
fi

if [ -z ${WORKER_CONCURRENCY+x} ]; then
export WORKER_CONCURRENCY=${WORKERS_TOTAL}
fi
3 changes: 1 addition & 2 deletions config/supervisord.conf.example
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ stdout_logfile=%(ENV_WORKER_HOME)s/logs/filetracker-cache-cleaner.log


[program:oioioiworker]
command=twistd -n -l- --pidfile=%(ENV_WORKER_HOME)s/pidfiles/oioioiworker.pid worker -c %(ENV_WORKER_CONCURRENCY)s -r %(ENV_WORKER_RAM)s -l %(ENV_WORKER_LOGCONFIG)s %(ENV_SIOWORKERSD_HOST)s
command=twistd -n -l- --pidfile=%(ENV_WORKER_HOME)s/pidfiles/oioioiworker.pid worker -c %(ENV_WORKER_CONCURRENCY)s -r %(ENV_WORKER_RAM)s -l %(ENV_WORKER_LOGCONFIG)s %(ENV_WORKER_EXTRA_FLAGS)s %(ENV_SIOWORKERSD_HOST)s
autostart=%(ENV_WORKER_ENABLED)s
priority=100
redirect_stderr=true
Expand All @@ -39,4 +39,3 @@ supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix://%(ENV_WORKER_HOME)s/supervisor.sock

6 changes: 6 additions & 0 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash
set -e

. /sio2/venv/bin/activate

exec "$@"
21 changes: 14 additions & 7 deletions supervisor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Options:

Commands:
start starts supervisor
startfg starts supervisor in foreground
stop stops supervisor
restart restart supervisor
status shows status of daemons that supervisor run
Expand All @@ -25,7 +26,7 @@ while [ -n "$1" ]; do
help
exit 0
;;
"start"|"stop"|"restart"|"status"|"shell")
"start"|"startfg"|"stop"|"restart"|"status"|"shell")
command="$1"
;;
*)
Expand Down Expand Up @@ -54,7 +55,10 @@ if ! [ -e supervisord.conf ] || \
fi

# Activate venv:
source ../../venv/bin/activate
if [ -d "../../venv" ]
then
source ../../venv/bin/activate
fi

# Set all config variables.
source supervisord-conf-vars.conf
Expand All @@ -72,20 +76,23 @@ mkdir -pv "${WORKER_HOME}"/{logs,pidfiles}
# And run supervisor.*
case "$command" in
"start")
supervisord
exec supervisord
;;
"startfg")
exec supervisord -n
;;
"stop")
supervisorctl shutdown
exec supervisorctl shutdown
;;
"restart")
supervisorctl shutdown
supervisord
exec supervisord
;;
"status")
supervisorctl status
exec supervisorctl status
;;
"shell")
echo "Caution: In order to reload config, run \`$0 restart\`"
supervisorctl
exec supervisorctl
;;
esac