The Execution Engine is designed to execute large volumes of foreign code securely in containerized environments. Leveraging Docker for isolation and Bull MQ for task queuing, this system ensures each code submission runs in an isolated container without network access, preventing unauthorized actions. This project highlights backend technologies like message queues, workers, and containerization, showcasing scalable and secure systems.
- Execution in Isolated Environments: Code runs within Docker containers, providing complete isolation from the host system.
- No Network Access: Containers have no network access, ensuring secure execution of potentially untrusted code.
- Cloud Output Storage: Execution logs (stdout and stderr) are saved to Google Cloud Storage, providing scalable and secure access to output.
- C++ Support: Currently supports C++ code execution, with plans for future support of additional languages.
- Docker: Containerization to securely run user-submitted code in isolated environments.
- Docker Compose: Orchestrates multiple services locally for simplified setup.
- Bull MQ: Built on Redis, it manages execution queues and processes tasks efficiently.
- Redis: Message broker for handling job queues.
- PostgreSQL: Relational database for storing job metadata and execution results.
- Google Cloud Storage: Used to store and retrieve execution outputs securely.
- Bull MQ: Manages task queues, distributing execution jobs to worker processes running in isolated threads.
- Docker Containers: Ensure code execution is secure and sandboxed, with no network access and limited system resources.
- Worker Threads: Handles CPU-bound execution tasks efficiently in a scalable, responsive architecture.
Submit code via file upload.
- Request:
- Method:
POST - Type:
multipart/form-data - Field:
sourceCode(file)
- Method:
- Response:
{ "message": "File uploaded and pushed to queue successfully", "id": "<id>", "fileName": "<fileName with extension>" }
Submit code by providing a URL to the file.
- Request:
- Method:
POST - Type:
application/json - Body:
{ "url": "<url_link_of_file>" }
- Method:
- Response:
{ "message": "File uploaded and pushed to queue successfully", "id": "<id>", "fileName": "<fileName with extension>" }
Get the output link after code execution.
- Request:
- Method:
GET - Query Parameter:
id
- Method:
- Response:
{ "message": "Executed URL fetched successfully", "codeId": "<id>", "executedUrl": "<downloadable url expires in 30 min>" }
Follow these steps to set up the project locally:
-
Ensure you have Docker and Docker Compose installed.
-
You need to mount your
serviceAccount.jsfile, which contains Firebase configurations (such asconfig,storageBucket,firebase database url, anduploadDestination).- Place the
serviceAccount.jsfile in the/home/aryan/judge0/config/directory. If you don’t have it, copy and modify/config/serviceAccountDemo.jswith your Firebase credentials.
The relevant volume setup in
docker-compose.yml:volumes: - /home/aryan/judge0:/app/judge0 - /home/aryan/judge0/config/serviceAccount.js:/app/judge0/config/serviceAccount.js - /var/run/docker.sock:/var/run/docker.sock
- Place the
-
Ensure that the
storageBucketinserviceAccount.jsmatches your Firebase bucket address, and thefirebase database urlis set to your Firebase Realtime Database. -
Start the services by running:
docker-compose up
- Support for More Languages: The engine currently supports only C++. Future updates will include support for additional programming languages.
- Real-Time Resource Monitoring: Implementing real-time resource monitoring for containers, enforcing strict CPU and memory limits during code execution.
This project reflects my passion for backend development, utilizing containerization, message queues, and concurrency to build secure, scalable systems. Future updates will continue to enhance the system's capabilities and performance.