Docker-Based Execution
Runtime uses Docker containers to provide isolated, reproducible execution environments for each code snippet. Every execution runs in a fresh container that is created, executed, and destroyed automatically.
Docker Client Configuration
The system connects to Docker using the Docker Java API client.
Location: DockerExecutorUtil.java:24-35
public DockerExecutorUtil () {
DefaultDockerClientConfig config = DefaultDockerClientConfig
. createDefaultConfigBuilder ()
. withDockerHost ( "tcp://localhost:2375" )
. build ();
ApacheDockerHttpClient httpClient = new ApacheDockerHttpClient. Builder ()
. dockerHost ( config . getDockerHost ())
. build ();
this . dockerClient = DockerClientImpl . getInstance (config, httpClient);
}
The Docker daemon is accessed via TCP on port 2375. Ensure Docker is configured to listen on this port.
Execution Workflow
Step 1: Temporary Directory Setup
Each execution gets a unique temporary directory to store source code.
Location: DockerExecutorUtil.java:41-46
String tempDirPath = System . getProperty ( "java.io.tmpdir" ) + "/code_" + UUID . randomUUID ();
Path tempDir = Paths . get (tempDirPath);
Files . createDirectories (tempDir);
String fileName = getFileName (language, code);
Files . writeString ( tempDir . resolve (fileName), code);
Example Path: /tmp/code_a3f8c9d2-4b7e-4a1f-9c3e-8d2f1a6b5c4e/Contents: Source file (Main.java, main.py, etc.)
Step 2: Container Creation
A Docker container is created with the appropriate image and resource limits.
Location: DockerExecutorUtil.java:48-58
String dockerImage = getDockerImage (language);
String [] command = getRunCommand (language, code);
CreateContainerResponse container = dockerClient . createContainerCmd (dockerImage)
. withCmd (command)
. withHostConfig ( HostConfig . newHostConfig ()
. withBinds ( new Bind (tempDirPath, new Volume ( "/code" )))
. withMemory ( 128 * 1024 * 1024L )
. withNanoCPUs ( 500_000_000L ))
. withWorkingDir ( "/code" )
. exec ();
String containerId = container . getId ();
Volume Binding
The temporary directory is mounted into the container at /code:
Host: /tmp/code_a3f8c9d2-4b7e-4a1f-9c3e-8d2f1a6b5c4e/
↓ (bind mount)
Container: /code/
Step 3: Container Execution
The container starts and waits for completion.
Location: DockerExecutorUtil.java:62-64
dockerClient . startContainerCmd (containerId). exec ();
System . out . println ( "Docker container started!!!" );
dockerClient . waitContainerCmd (containerId). start (). awaitStatusCode ();
Step 4: Output Capture
Both stdout and stderr streams are captured from the container logs.
Location: DockerExecutorUtil.java:68-84
StringBuilder output = new StringBuilder ();
StringBuilder error = new StringBuilder ();
dockerClient . logContainerCmd (containerId)
. withStdOut ( true )
. withStdErr ( true )
. exec ( new com . github . dockerjava . api . async . ResultCallback . Adapter < Frame >() {
@ Override
public void onNext ( Frame frame ) {
String log = new String ( frame . getPayload ());
if ( frame . getStreamType (). name (). equals ( "STDOUT" )) {
output . append (log);
} else {
error . append (log);
}
}
}). awaitCompletion ();
Step 5: Cleanup
The container and temporary directory are removed.
Location: DockerExecutorUtil.java:86-88
dockerClient . removeContainerCmd (containerId). exec ();
System . out . println ( "Docker container removed!!!" );
deleteDirectory ( tempDir . toFile ());
Containers are always removed after execution, even if the code fails. This prevents container buildup.
Language-Specific Execution
Docker Images
Each language uses a specific Docker image optimized for that runtime.
Location: DockerExecutorUtil.java:119-127
private String getDockerImage ( String language) {
return switch ( language . toLowerCase ()) {
case "java" -> "eclipse-temurin:17" ;
case "python" -> "python:3.11" ;
case "c" , "cpp" -> "gcc:latest" ;
case "javascript" -> "node:18" ;
default -> throw new IllegalArgumentException ( "Unsupported language: " + language);
};
}
eclipse-temurin:17 Official Eclipse Temurin JDK 17 for Java execution
python:3.11 Official Python 3.11 image
gcc:latest GCC compiler for C and C++ programs
node:18 Node.js 18 runtime for JavaScript
Execution Commands
Each language has a specific command sequence for compilation and execution.
Location: DockerExecutorUtil.java:129-141
private String [] getRunCommand ( String language, String code) {
return switch ( language . toLowerCase ()) {
case "java" -> {
String className = extractJavaClassName (code);
yield new String []{ "sh" , "-c" , "javac " + className + ".java && java " + className};
}
case "python" -> new String []{ "sh" , "-c" , "python main.py" };
case "c" -> new String []{ "sh" , "-c" , "gcc main.c -o main && ./main" };
case "cpp" -> new String []{ "sh" , "-c" , "g++ main.cpp -o main && ./main" };
case "javascript" -> new String []{ "sh" , "-c" , "node main.js" };
default -> throw new IllegalArgumentException ( "Unsupported language: " + language);
};
}
Java
Python
C
C++
JavaScript
javac Main.java && java Main
Compiles the .java file and runs the class Runs the Python script directly gcc main.c -o main && ./main
Compiles C code and executes the binary g++ main.cpp -o main && ./main
Compiles C++ code and executes the binary Runs JavaScript with Node.js
File Naming
File names are determined based on the language and code content.
Location: DockerExecutorUtil.java:108-117
private String getFileName ( String language, String code) {
return switch ( language . toLowerCase ()) {
case "java" -> extractJavaClassName (code) + ".java" ;
case "python" -> "main.py" ;
case "c" -> "main.c" ;
case "cpp" -> "main.cpp" ;
case "javascript" -> "main.js" ;
default -> throw new IllegalArgumentException ( "Unsupported language: " + language);
};
}
Java Class Name Extraction
Resource Limits
Every container is created with strict resource constraints:
Maximum RAM allocated per container: 128 * 1024 * 1024L bytes
CPU limit in nanoseconds: 500_000_000L (0.5 cores)
. withHostConfig ( HostConfig . newHostConfig ()
. withBinds ( new Bind (tempDirPath, new Volume ( "/code" )))
. withMemory ( 128 * 1024 * 1024L ) // 128MB
. withNanoCPUs ( 500_000_000L )) // 0.5 CPU cores
These limits prevent resource exhaustion and ensure fair usage across multiple concurrent executions.
Execution Result
The execution result includes output, exit code, and timing information.
Location: DockerExecutorUtil.java:91-93
String finalOutput = ! output . isEmpty () ? output . toString () : error . toString ();
ExecutionResult result = new ExecutionResult (finalOutput, 0 , executionTime);
return ApiResponse . success ( "Code Executed successfully" , result);
ExecutionResult Model:
public class ExecutionResult {
private String output ; // Combined stdout/stderr
private int exitCode ; // Process exit code
private long executionTime ; // Time in milliseconds
}
Error Handling
All exceptions during execution are caught and returned as error responses.
Location: DockerExecutorUtil.java:95-97
catch ( Exception e ) {
return ApiResponse . error ( "Execution failed: " + e . getMessage ());
}
Graceful Degradation: Even if execution fails, containers are cleaned up and a meaningful error message is returned to the client.
Next Steps
Security Features Learn about isolation and security mechanisms
API Reference View the execution API endpoint documentation