The Kodex Server is the backend service for the Kodex platform, handling code execution, API requests, and database interactions. Built with Express.js, Docker, and Prisma, it supports dynamic, multi-language code execution environments and integrates seamlessly with the Kodex frontend.
Check out the demonstration of the Kodex Server in action:
- Requirements
- Setup
- Directory Structure
- Running the Server
- API Endpoints
- Docker Configuration
- Middleware
- Adding new Language Support
- Node.js (version 14 or higher)
- Docker (with dynamic container management support)
- Docker Compose
-
Clone the Repository:
git clone https://github.com/ViragJain3010/Kodex-Server cd kodex/server
-
Install Dependencies:
npm install
-
Configure the Environment:
- Create a
.env
file in thekodex/server
directory based on the provided .env.example template. - Configure environment variables for database connection, Docker settings, and other server options.
- Create a
-
Build and Run Docker Containers:
docker compose build docker compose up # For testing, if ran successfully then execute `docker compose down`
Tip: If you encounter errors,try restarting the terminal and rerun the commands.
api/
: Express routes for handling API requests.config/
: Configuration files.docker/
: Dockerfile and related configuration filesexecutors/
: Code execution logic for supported programming languages.middleware/
: Custom Express middleware functions.prisma/
: Prisma ORM schema and client configuration.standalone/
: Standalone Next.js build for the frontend (used in production).utils/
: Utility functions and helper classes.
-
Production Mode:
npm run dev
Uses the frontend build in the
standalone
folder for testing. -
Devlopment Mode:
npm start
Starts the backend server at
localhost:3001
. The frontend needs to be started separately in another terminal, after which it can communicate with the backend via API requests.
-
POST /api/execute
Executes code in the specified programming language.
Request Body:{ "language": "python", "code": "print('Hello, World!')", "input": "" }
-
GET /api/languages
Retrieves a list of supported programming languages. -
Get /api/languages/{language}
Retrieves the configuration of a specific language.
POST /api/test
A utility endpoint for server testing (development purposes only).
Docker dynamically creates and manages containers for secure, isolated code execution.
Key Configuration:
docker-compose.yml
: Defines services and networks for the backend and execution environments.- Docker Services:
javascript-runner
: Runs JavaScript code.python-runner
: Runs Python code.cpp-runner
: Runs C++ code.
- Docker Networks:
code-network
: A bridge network for communication between containers.Note: Ensure this network is created to avoid errors.
- To Create the Docker Network
Run the following command:
docker network create code-network
code-network
is the name of the network used in your docker-compose.yml file. You can replace it with any other name, but ensure consistency in your configuration.
Custom middleware functions are implemented in the middleware/
directory.
The language setup is divided into three parts:
- Docker Setup
- Language Configuration
- Executor Class Setup
Follow the steps below to integrate a new programming language into the system:
- Inside the docker directory, create a new folder for your language.
- Add a
Dockerfile
to this folder to define the environment for code execution.- Ensure the Dockerfile has all the necessary tools and configurations for the language.
- Please see the base Dockerfile for example.
- Update the docker-compose.yml file:
- Add a service configuration for the new language.
- Verify the paths for
context
,dockerfile
,volumes
, andworking_dir
are correct.
Add the language details to the Languages.config.js file. Use the following structure:
languages = {
key: { // Unique identifier for the language
name: "Language Name", // Display name for the dropdown
extension: ".ext", // File extension for the language
docker: {
image: "docker-image-name", // Docker image name
workDir: "/app", // Container working directory
timeout: 10000, // Max runtime in ms
memory: "128mb", // Memory allocation
cpus: "0.5", // CPU allocation
},
execution: {
command: "command", // Command to execute the code
compileCommand: "compile command", // Compilation command, if required
filePrefix: "file", // Prefix for generated code files
defaultBoilerplate: "code", // Default code template
},
settings: {
supportsInput: boolean, // Whether the language supports standard input
supportsFiles: boolean, // Whether file handling is supported
requiresCompilation: boolean, // Whether compilation is required
},
},
};
Note: Ensure all fields are correctly filled to prevent unexpected errors.
- Create a new executor class for the language inside the executors directory.
- Follow the structure of the existing executor classes to implement the logic for:
- Code execution
- Handling pre- and post-execution tasks
- Managing inputs and outputs
After completing the above steps:
-
Build the Docker images using the following command:
docker compose build
-
Test the setup by running:
docker compose up
- If the containers run successfully, stop them using:
docker compose down
- If the containers run successfully, stop them using:
This structure ensures safety and high customization for pre- and post-code execution. It makes the system highly robust against misuse and allows complete customization of the execution environment as needed.