Package: epicboxie
EpicboxieForked fromStepicOrg/epicboxfor some improvements.This fork allows to expose container ports with host machine and to work with sandbox interactively.epicboxie.run_interactiveis a context manager that runs sandbox:importtimeimportrequestsimportepicboxieepicboxie.configure(profiles=[epicboxie.Profile('python','python:3.6.5-alpine')])withopen('server.py','rb')asf:contents=f.read()files=[{'name':'main.py','content':contents}]limits={'cputime':1,'memory':64}ports={8000:8000}withepicboxie.run_interactive('python','python3 main.py',files=files,limits=limits,ports=ports)asrun:time.sleep(2)print(requests.get('http://localhost:8000').status_code)result=run.resultsTheportsparameter is also added to oldrunfunction.Interaction with standard I/O is done withrun.docker_interaction.read_sock()andrun.docker_interaction.write_sock():importtimeimportrequestsimportepicboxieepicboxie.configure(profiles=[epicboxie.Profile('python','python:3.6.5-alpine')])files=[{'name':'main.py','content':b'print(input("Input data: ")[::-1])'}]limits={'cputime':1,'memory':64}ports={8000:8000}withepicboxie.run_interactive('python','python3 main.py',files=files,limits=limits,ports=ports)asrun:time.sleep(0.5)prompt=run.docker_interaction.read_sock()[0].decode('utf8')# read_sock returns tuple (stdout, stderr)run.docker_interaction.write_sock(input(prompt).encode())time.sleep(0.5)print(run.docker_interaction.read_sock()[0].decode('utf8'))result=run.resultsIf you need to use old-style automatic interaction (pass whole stdin and wait for termination) when usingrun_interactive, you can userun.docker_interaction.interact(stdin, timeout, close=True)Original README.md:epicboxA Python library to run untrusted code in secure, isolatedDockerbased sandboxes. It is used to automatically grade programming assignments
onStepik.org.It allows to spawn a process inside one-time Docker container, send data
to stdin, and obtain its exit code and stdout/stderr output.  It's very similar
to what thesubprocessmodule does but additionally you can specify a custom environment for the process
(a Dockerimage)
and limit the CPU, memory, disk, and network usage for the running process.UsageRun a simple Python script in a one-time Docker container using thepython:3.6.5-alpineimage:importepicboxieepicboxie.configure(profiles=[epicboxie.Profile('python','python:3.6.5-alpine')])files=[{'name':'main.py','content':b'print(42)'}]limits={'cputime':1,'memory':64}result=epicbox.run('python','python3 main.py',files=files,limits=limits)Theresultvalue is:{'exit_code':0,'stdout':b'42\n','stderr':b'','duration':0.143358,'timeout':False,'oom_killed':False}Available Limit OptionsThe available limit options and default values:DEFAULT_LIMITS = {
    # CPU time in seconds, None for unlimited
    'cputime': 1,
    # Real time in seconds, None for unlimited
    'realtime': 5,
    # Memory in megabytes, None for unlimited
    'memory': 64,

    # limit the max processes the sandbox can have
    # -1 or None for unlimited(default)
    'processes': -1,
}Advanced usageA more advanced usage example ofepicboxis to compile a C++ program and then
run it multiple times on different input data.  In this exampleepicboxwill
run containers on a dedicatedDocker Swarmcluster instead of locally installed Docker engine:importepicboxiePROFILES={'gcc_compile':{'docker_image':'stepik/epicboxie-gcc:6.3.0','user':'root',},'gcc_run':{'docker_image':'stepik/epicboxie-gcc:6.3.0',# It's safer to run untrusted code as a non-root user (even in a container)'user':'sandbox','read_only':True,'network_disabled':False,},}epicboxie.configure(profiles=PROFILES,docker_url='tcp://1.2.3.4:2375')untrusted_code=b"""// C++ program#include <iostream>int main() {int a, b;std::cin >> a >> b;std::cout << a + b << std::endl;}"""# A working directory allows to preserve files created in a one-time container# and access them from another one. Internally it is a temporary Docker volume.withepicboxie.working_directory()asworkdir:epicboxie.run('gcc_compile','g++ -pipe -O2 -static -o main main.cpp',files=[{'name':'main.cpp','content':untrusted_code}],workdir=workdir)epicboxie.run('gcc_run','./main',stdin='2 2',limits={'cputime':1,'memory':64},workdir=workdir)# {'exit_code': 0, 'stdout': b'4\n', 'stderr': b'', 'duration': 0.095318, 'timeout': False, 'oom_killed': False}epicboxie.run('gcc_run','./main',stdin='14 5',limits={'cputime':1,'memory':64},workdir=workdir)# {'exit_code': 0, 'stdout': b'19\n', 'stderr': b'', 'duration': 0.10285, 'timeout': False, 'oom_killed': False}Installationepicboxcan be installed by runningpip install epicbox. It's tested on Python 3.4+ and
Docker 1.12+.You can also check theepicbox-imagesrepository that contains Docker images used to automatically grade programming
assignments onStepik.org.ContributingContributions are welcome, and they are greatly appreciated!
More details can be found inCONTRIBUTING.