Our various track tooling are deployed as Docker images.
Each piece of tooling requires a Dockerfile, which specifies how the machine is built.
It should live at the root directory of your repository and should be called Dockerfile
.
The Dockerfile should create the minimal image needed for the tooling to function correctly and speedily. Our Best Practices page has lots of tips to help you achieve this goal.
The test runner gets 100% CPU with 3GB of memory for a 20 second window per solution. After 20 seconds, the process is halted and reports a time-out with a 408 error code.
We highly recommend following our Performance Best Practices document to reduce the chance of timeouts.
A tooling run may produce up to a maximum of one-megabyte of stdout and stderr. If it produces more, it will be killed with a 413 error code.
The contents of stdout
and stderr
from each run will be stored in files.
You may write a results.out
file to the output directory, which contains debugging information.
Right now, it is not possible for maintainers to view the contents of these files.
The results file may not be larger than 500 kilobytes (including any stack traces etc). If the file is larger than this, the tooling run will be killed with a 460 error code.
Each solution gets 100% machine resources for a twenty second window. After 20 seconds, the process is halted and reports as a time-out.
Some tools require (slight) deviations from the default configuration.
If so, these are configured in the tools.json
file in the Tooling Invoker repository.
Tools run without access to the internet. There are two different configurations you can use:
none
. This disables the networking device inside the container.internal
. This adds a networking device inside the container but the network has no access to anything external.Different languages perform better/worse with different configurations (e.g. Ruby is 2x faster with none
. Elixir is 12x
faster with internal
.
You can experiment locally by using the --network
flag when running your docker. --network none
is supported by default.
To use the internal network, first run docker network create --internal internal
to create the network, then use --network internal
when running the container.
Languages can set the maximum memory they need to use to run their jobs. Setting this to be as low as possible means that we can run more jobs more quickly in parallel. It also means that people who try and abuse memory will not be able to succeed. Different languages need wildly different maximum memory usage. Benchmarking the execution of a docker run to establish the maximum memory it uses is advised and appreciated.
Memory should be specified using the number with suffix of b, k, m, g, to indicate bytes, kilobytes, megabytes, or gigabytes.
You can test the settings above using this command:
docker container run -v /path/to/job:/mnt/exercism-iteration --network none -m 1GB exercism/ruby-test-runner lasagna /mnt/exercism-iteration/ /mnt/exercism-iteration/
All changes to Dockerfiles require a PR review from the @exercism/maintainers-admin
team, in order to avoid the introduction of security exploits.