Un entorno de ejecución de código Java en línea, construido con Node.js, TypeScript, Docker y React. Este proyecto permite ejecutar código Java de forma segura en contenedores aislados directamente desde el navegador.
Nota: Este proyecto fue creado con fines educativos como parte de mi portafolio de desarrollo. No cuenta con derechos reservados y está disponible para aprendizaje y referencia.
- Ejecución segura de código Java: Utiliza contenedores Docker aislados con límites de recursos
- API REST: Backend construido con Express y TypeScript
- Límites de recursos: Control de memoria (128MB), CPU (0.5 cores) y timeout (5 segundos)
- Detección automática de código: Envuelve automáticamente snippets simples en una clase Main
- Frontend moderno: Interfaz de usuario construida con React y Vite
- Arquitectura en contenedores: Completamente dockerizada con Docker Compose
- Proxy inverso: Nginx para enrutamiento y servir archivos estáticos
┌─────────────────┐
│ Nginx Proxy │
│ (Port 80) │
└────────┬────────┘
│
┌────┴────────────────────┐
│ │
┌───▼──────┐ ┌───────▼────────┐
│ Frontend │ │ Backend │
│ (React) │ │ (Node.js/TS) │
└──────────┘ └───────┬────────┘
│
┌───────▼────────┐
│ Docker Socket │
│ Java Runner │
└────────────────┘
- Frontend: React + Vite + TypeScript
- Backend: Node.js + Express + TypeScript
- Java Runner: Contenedor Docker con OpenJDK 21
- Nginx: Proxy inverso y servidor de archivos estáticos
- Red: Red Docker personalizada (
ortega-net)
- Docker (v20.10+)
- Docker Compose (v2.0+)
- Node.js (v22+) - solo para desarrollo local
- NPM o Bun
git clone https://github.com/llOrtegall/java-online.git
cd java-onlinedocker network create ortega-netcd backend
npm run docker:buildcd ..
docker compose up -d --buildGET /healthRespuesta:
{
"status": "ok",
"service": "java-playground-backend"
}GET /check-dockerRespuesta:
{
"dockerAvailable": true,
"imageReady": true,
"message": "Docker image ready",
"dockerImagesStdout": "3f1ca98236d2\n",
"dockerImagesStderr": ""
}POST /execute
Content-Type: application/json
{
"code": "System.out.println(\"Hello World!\");"
}Respuesta exitosa:
{
"success": true,
"output": "Hello World!\n",
"executionTime": 1684
}Respuesta con error:
{
"success": false,
"error": "error: ';' expected\n...",
"executionTime": 525
}System.out.println("Hello from Java!");
int x = 10;
int y = 20;
System.out.println("Sum: " + (x + y));public class Main {
public static void main(String[] args) {
for(int i = 1; i <= 5; i++) {
System.out.println("Number: " + i);
}
}
}cd backend
npm install
npm run devEl servidor se iniciará en http://localhost:4000
cd frontend
npm install
npm run devEl frontend se iniciará en http://localhost:5173
java-online/
├── backend/
│ ├── src/
│ │ ├── index.ts # Servidor Express principal
│ │ ├── services/
│ │ │ └── javaExecutor.ts # Lógica de ejecución de Java
│ │ └── types/
│ │ └── index.ts # Definiciones de tipos
│ ├── Dockerfile # Imagen del backend
│ ├── Dockerfile.java-runner # Imagen del runner de Java
│ ├── build-docker-image.sh # Script de construcción
│ ├── package.json
│ └── tsconfig.json
├── frontend/
│ ├── src/
│ │ ├── App.tsx # Componente principal
│ │ ├── main.tsx # Punto de entrada
│ │ └── assets/
│ ├── public/
│ ├── nginx.conf # Configuración de Nginx
│ ├── package.json
│ └── vite.config.ts
├── docker-compose.yaml # Orquestación de servicios
└── README.md
El proyecto implementa varias medidas de seguridad para la ejecución de código:
- Contenedores aislados: Cada ejecución corre en un contenedor Docker separado
- Límites de recursos:
- Memoria: 128MB
- CPU: 0.5 cores
- PIDs: 50 procesos máximo
- Timeout: 5 segundos
- Límite de código: Máximo 10,000 caracteres
- Limpieza automática: Los archivos temporales se eliminan después de cada ejecución
- Sin persistencia: Los contenedores se destruyen después de la ejecución (
--rm)
- Backend:
node:22-alpinecon Docker CLI - Java Runner:
openjdk:21-slim - Nginx:
nginx:stable-alpine3.21
/var/run/docker.sock: Socket de Docker para ejecutar contenedores desde el backend/tmp:/tmp: Directorio temporal compartido para archivos Java
PORT=4000 # Puerto del backendnpm run dev # Modo desarrollo con hot-reload
npm run build # Compilar TypeScript a JavaScript
npm start # Iniciar servidor en producción
npm run docker:build # Construir imagen del runner de Java
npm run docker:check # Verificar imagen del runner
npm run setup # Configuración inicial completanpm run dev # Servidor de desarrollo
npm run build # Compilar para producción
npm run preview # Vista previa de la build
npm run lint # Ejecutar ESLint# Verificar que la imagen existe
docker images | grep java-runner
# Reconstruir la imagen
cd backend && npm run docker:build# Reconstruir el backend
docker compose build java-backend
docker compose up -d java-backendEl timeout por defecto es de 5 segundos. Para código que requiere más tiempo, ajusta el valor en backend/src/index.ts:
const result = await javaExecutor.executeJavaCode(code, {
timeout: 10000, // 10 segundos
memoryLimit: '128m',
cpus: '0.5',
});Este proyecto es principalmente educativo, pero las contribuciones son bienvenidas. Si deseas mejorar el código:
- Fork el proyecto
- Crea una rama para tu feature (
git checkout -b feature/amazing-feature) - Commit tus cambios (
git commit -m 'Add some amazing feature') - Push a la rama (
git push origin feature/amazing-feature) - Abre un Pull Request
Este proyecto fue creado con fines educativos y está disponible libremente para aprendizaje y referencia. No cuenta con derechos reservados.
Uso educativo: Puedes usar, modificar y distribuir este código para propósitos de aprendizaje.
llOrtegall
- GitHub: @llOrtegall
- Proyecto: java-online
- OpenJDK por el compilador y runtime de Java
- Docker por la tecnología de contenedores
- Node.js y Express por el framework del backend
- React y Vite por las herramientas de frontend
- La comunidad de código abierto
⭐ Si este proyecto te fue útil para aprender, considera darle una estrella en GitHub!