Skip to content

Latest commit

 

History

History
334 lines (257 loc) · 8.44 KB

File metadata and controls

334 lines (257 loc) · 8.44 KB

☕ Java Online Playground

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.

🚀 Características

  • 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

🏗️ Arquitectura

┌─────────────────┐
│   Nginx Proxy   │
│   (Port 80)     │
└────────┬────────┘
         │
    ┌────┴────────────────────┐
    │                         │
┌───▼──────┐          ┌───────▼────────┐
│ Frontend │          │    Backend     │
│  (React) │          │  (Node.js/TS)  │
└──────────┘          └───────┬────────┘
                              │
                      ┌───────▼────────┐
                      │  Docker Socket │
                      │  Java Runner   │
                      └────────────────┘

Componentes

  • 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)

📋 Requisitos Previos

  • Docker (v20.10+)
  • Docker Compose (v2.0+)
  • Node.js (v22+) - solo para desarrollo local
  • NPM o Bun

🛠️ Instalación

1. Clonar el repositorio

git clone https://github.com/llOrtegall/java-online.git
cd java-online

2. Crear la red Docker

docker network create ortega-net

3. Construir la imagen del runner de Java

cd backend
npm run docker:build

4. Construir y levantar los servicios

cd ..
docker compose up -d --build

🎯 Uso

API Endpoints

Health Check

GET /health

Respuesta:

{
  "status": "ok",
  "service": "java-playground-backend"
}

Verificar Docker

GET /check-docker

Respuesta:

{
  "dockerAvailable": true,
  "imageReady": true,
  "message": "Docker image ready",
  "dockerImagesStdout": "3f1ca98236d2\n",
  "dockerImagesStderr": ""
}

Ejecutar código Java

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
}

Ejemplos de código

Código simple (se envuelve automáticamente)

System.out.println("Hello from Java!");
int x = 10;
int y = 20;
System.out.println("Sum: " + (x + y));

Clase completa

public class Main {
    public static void main(String[] args) {
        for(int i = 1; i <= 5; i++) {
            System.out.println("Number: " + i);
        }
    }
}

🔧 Desarrollo Local

Backend

cd backend
npm install
npm run dev

El servidor se iniciará en http://localhost:4000

Frontend

cd frontend
npm install
npm run dev

El frontend se iniciará en http://localhost:5173

📁 Estructura del Proyecto

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

🔒 Seguridad

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)

🐳 Docker

Imágenes utilizadas

  • Backend: node:22-alpine con Docker CLI
  • Java Runner: openjdk:21-slim
  • Nginx: nginx:stable-alpine3.21

Volúmenes

  • /var/run/docker.sock: Socket de Docker para ejecutar contenedores desde el backend
  • /tmp:/tmp: Directorio temporal compartido para archivos Java

Variables de entorno

PORT=4000  # Puerto del backend

📊 Scripts Disponibles

Backend

npm 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 completa

Frontend

npm 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

🚨 Solución de Problemas

El backend no detecta la imagen de Java

# Verificar que la imagen existe
docker images | grep java-runner

# Reconstruir la imagen
cd backend && npm run docker:build

Error "Cannot find module '/app/dist/index.js'"

# Reconstruir el backend
docker compose build java-backend
docker compose up -d java-backend

Timeout en la ejecución

El 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',
});

🤝 Contribuciones

Este proyecto es principalmente educativo, pero las contribuciones son bienvenidas. Si deseas mejorar el código:

  1. Fork el proyecto
  2. Crea una rama para tu feature (git checkout -b feature/amazing-feature)
  3. Commit tus cambios (git commit -m 'Add some amazing feature')
  4. Push a la rama (git push origin feature/amazing-feature)
  5. Abre un Pull Request

📝 Licencia

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.

👨‍💻 Autor

llOrtegall

🙏 Agradecimientos

  • 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!