diff --git a/online_compiler/Dockerfile.api b/online_compiler/Dockerfile.api new file mode 100644 index 0000000..498691f --- /dev/null +++ b/online_compiler/Dockerfile.api @@ -0,0 +1,11 @@ +FROM rust:latest + +WORKDIR /app + +COPY api . + +RUN cargo build --release + +EXPOSE 8000 + +CMD ["cargo", "run", "--release"] \ No newline at end of file diff --git a/online_compiler/Dockerfile.web b/online_compiler/Dockerfile.web new file mode 100644 index 0000000..b475184 --- /dev/null +++ b/online_compiler/Dockerfile.web @@ -0,0 +1,11 @@ +FROM rust:latest + +WORKDIR /app + +COPY web . + +RUN cargo build --release + +EXPOSE 80 + +CMD ["cargo", "run", "--release"] \ No newline at end of file diff --git a/online_compiler/REDME.md b/online_compiler/REDME.md new file mode 100644 index 0000000..45543ca --- /dev/null +++ b/online_compiler/REDME.md @@ -0,0 +1,122 @@ +README.md + +markdown +深色版本 + +# 在线编译器项目 + +这是一个简单的在线编译器项目,用户可以通过Web界面输入代码并选择编程语言,然后执行代码并查看结果。该项目由两部分组成: + +- **API服务**:负责接收代码执行请求,使用Docker容器来执行代码,并返回结果。 +- **Web服务**:提供一个用户界面,允许用户输入代码并查看执行结果。 + +## 项目结构 + +online-compiler +├── api +│ ├── Cargo.toml +│ ├── src +│ │ └── main.rs +├── web +│ ├── Cargo.toml +│ ├── src +│ │ └── main.rs +│ ├── static +│ │ ├── styles.css +│ │ ├── scripts.js +│ │ └── index.html +├── Dockerfile.api +├── Dockerfile.web +└── docker-compose.yml + +深色版本 + + +## 快速开始 + +1. 确保你已经安装了[Docker](https://docs.docker.com/get-docker/)和[Docker Compose](https://docs.docker.com/compose/install/)。 +2. 克隆此仓库到你的本地机器。 +3. 进入项目根目录。 +4. 使用以下命令启动项目: + + ```bash + docker-compose up --build + + 打开浏览器访问 http://localhost 来使用在线编译器。 + +API文档 +执行代码 + + URL: /api/v1/execute + + 方法: POST + + 请求体 (JSON): + + json + 深色版本 + +{ + "code": "print('Hello, world!')", + "language": "python" +} + +响应 (JSON): + +json +深色版本 + + { + "id": "b7c5f6a7-8d9a-4e00-9f5b-5a7c9f6b5d8e", + "status": "queued", + "response": null + } + + id: 执行任务的唯一标识符。 + status: 当前状态("queued", "compiling", "running", "completed")。 + response: 如果代码执行完成,则包含输出结果;否则为null。 + +查询执行状态 + + URL: /api/v1/status/{id} + + 方法: GET + + 路径参数: + id: 执行任务的唯一标识符。 + + 响应 (JSON): + + json + 深色版本 + + { + "id": "b7c5f6a7-8d9a-4e00-9f5b-5a7c9f6b5d8e", + "status": "completed", + "response": { + "stdout": "Hello, world!\n", + "stderr": "", + "returncode": 0 + } + } + + id: 执行任务的唯一标识符。 + status: 当前状态("queued", "compiling", "running", "completed")。 + response: 如果代码执行完成,则包含输出结果;否则为null。 + +示例 +执行代码示例 + +bash +深色版本 + +curl -X POST http://localhost:8000/api/v1/execute \ + -H "Content-Type: application/json" \ + -d '{"code":"print(\\\"Hello, world!\\\")","language":"python"}' + +查询状态示例 + +bash +深色版本 + +curl -X GET http://localhost:8000/api/v1/status/b7c5f6a7-8d9a-4e00-9f5b-5a7c9f6b5d8e diff --git a/online_compiler/api/.gitignore b/online_compiler/api/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/online_compiler/api/.gitignore @@ -0,0 +1 @@ +/target diff --git a/online_compiler/api/Cargo.lock b/online_compiler/api/Cargo.lock new file mode 100644 index 0000000..212259e --- /dev/null +++ b/online_compiler/api/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "api" +version = "0.1.0" diff --git a/online_compiler/api/Cargo.toml b/online_compiler/api/Cargo.toml new file mode 100644 index 0000000..ea307ef --- /dev/null +++ b/online_compiler/api/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "online_compiler_api" +version = "0.1.0" +edition = "2021" + +[dependencies] + + +hyper-tls = "0.6" # 确保这是最新的稳定版本 +native-tls = "0.2" # 明确指定 0.2 版本 + +rocket = { version = "0.5", features = ["json"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +uuid = "0.8" +tempfile = "3.1" +docker = "0.0.40" +tokio = { version = "1.0", features = ["full"] } +lazy_static = "1.4" +reqwest = { version = "0.12", features = ["json"] } + diff --git a/online_compiler/api/src/main.rs b/online_compiler/api/src/main.rs new file mode 100644 index 0000000..868dc55 --- /dev/null +++ b/online_compiler/api/src/main.rs @@ -0,0 +1,283 @@ +#[macro_use] extern crate rocket; +extern crate serde; +#[macro_use] extern crate serde_derive; +extern crate tokio; +extern crate uuid; +extern crate tempfile; +extern crate docker; +extern crate lazy_static; +extern crate reqwest; + +use rocket::response::content::Json; +use rocket::serde::{json::Json, Serialize, Deserialize}; +use std::process::Command; +use std::fs; +use std::io::Write; +use tempfile::NamedTempFile; +use uuid::Uuid; +use docker::Docker; +use docker::opts::{HostConfig, ResourceConstraints}; +use std::time::{Duration, Instant}; +use tokio::time::timeout; +use std::collections::HashMap; +use std::sync::{Arc, Mutex}; + +#[derive(Serialize, Deserialize, Debug)] +#[serde(crate = "rocket::serde")] +struct CodeRequest { + code: String, + language: String, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(crate = "rocket::serde")] +struct CodeResponse { + stdout: String, + stderr: String, + returncode: i32, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(crate = "rocket::serde")] +struct ExecutionStatus { + id: Uuid, + status: String, + response: Option, +} + +// 定义一个结构体来存储容器信息 +struct ContainerInfo { + container: docker::Container, + last_used: Instant, +} + +// 定义一个全局的容器缓存 +lazy_static! { + static ref CONTAINER_CACHE: Arc>> = Arc::new(Mutex::new(HashMap::new())); + static ref CONTAINER_LIMIT: Arc> = Arc::new(Mutex::new(0)); + static ref EXECUTION_STATUS: Arc>> = Arc::new(Mutex::new(HashMap::new())); +} + +async fn execute_code(code: &str, language: &str, execution_id: Uuid) -> Result { + // 获取 Docker 客户端 + let docker = Docker::connect_with_defaults().unwrap(); + + // 根据语言选择 Docker 镜像 + let image_name = match language { + "python" => "python-runner", + "rust" => "rust-runner", + "nim" => "nim-runner", + "lua" => "lua-runner", + _ => return Err("Unsupported language".to_string()), + }; + + // 创建临时文件 + let mut temp_file = NamedTempFile::new().unwrap(); + write!(temp_file, "{}", code).unwrap(); + let temp_path = temp_file.path().to_str().unwrap(); + + // 检查缓存中是否有可用的容器 + let mut cache = CONTAINER_CACHE.lock().unwrap(); + if let Some(container_info) = cache.get_mut(image_name) { + // 如果容器最近被使用过,则复用它 + if container_info.last_used.elapsed() < Duration::from_secs(3600) { // 1小时 + container_info.last_used = Instant::now(); + let (status, output) = timeout(Duration::from_secs(600), async { // 10分钟超时 + let status = container_info.container.wait(None).await.map_err(|e| e.to_string())?; + let logs = container_info.container.logs(true, true, None, None, None, None).await.map_err(|e| e.to_string())?; + (status, String::from_utf8(logs).unwrap()) + }).await.map_or_else( + |_| { + Err("Execution timed out".to_string()) + }, + |result| result + )?; + + // 解析输出 + let (stdout, stderr) = if status.success { + (output, String::new()) + } else { + (String::new(), output) + }; + + return Ok(CodeResponse { + stdout, + stderr, + returncode: status.exit_code.unwrap_or(-1) as i32, + }); + } + } + + // 创建新的容器 + let host_config = HostConfig { + resources: Some(ResourceConstraints { + memory: Some(128 * 1024 * 1024), // 128MB 内存限制 + cpu_shares: Some(1024), // CPU 资源限制 + ..Default::default() + }), + network_mode: Some("none".to_string()), // 禁用网络 + ..Default::default() + }; + + let container = docker.create_container( + Some(image_name), + vec!["/bin/sh", "-c", &format!("cat {} | {} -", temp_path, language)], + None, + Some(host_config), + None, + None, + None, + None, + None, + None, + None, + None, + ).await.map_err(|e| { + error!("Failed to create container: {}", e); + "Failed to create container".to_string() + })?; + + // 启动容器 + container.start(None).await.map_err(|e| { + error!("Failed to start container: {}", e); + "Failed to start container".to_string() + })?; + + // 设置超时时间为10分钟 + let timeout_duration = Duration::from_secs(600); + + let (status, output) = timeout(timeout_duration, async { + let status = container.wait(None).await.map_err(|e| e.to_string())?; + let logs = container.logs(true, true, None, None, None, None).await.map_err(|e| e.to_string())?; + (status, String::from_utf8(logs).unwrap()) + }).await.map_or_else( + |_| { + Err("Execution timed out".to_string()) + }, + |result| result + )?; + + // 将新的容器添加到缓存中 + cache.insert(image_name.to_string(), ContainerInfo { + container: container.clone(), + last_used: Instant::now(), + }); + + // 增加创建容器的计数 + let mut limit = CONTAINER_LIMIT.lock().unwrap(); + *limit += 1; + + // 检查是否超过每小时的最大创建数量 + if *limit > 3 { // 每小时最多创建3个新容器 + // 清理旧的容器 + for (key, value) in cache.iter_mut() { + if value.last_used.elapsed() > Duration::from_secs(3600) { + value.container.remove(None).await.ok(); + cache.remove(key); + } + } + *limit = 0; // 重置计数 + } + + // 解析输出 + let (stdout, stderr) = if status.success { + (output, String::new()) + } else { + (String::new(), output) + }; + + Ok(CodeResponse { + stdout, + stderr, + returncode: status.exit_code.unwrap_or(-1) as i32, + }) +} + +#[post("/api/v1/execute", format = "json", data = "")] +async fn handle_execute_code(request: Json) -> Result, rocket::response::status::Custom> { + let code_request = request.into_inner(); + let code = &code_request.code; + let language = &code_request.language; + let execution_id = Uuid::new_v4(); + + // 初始化执行状态 + let mut status_map = EXECUTION_STATUS.lock().unwrap(); + status_map.insert(execution_id, ExecutionStatus { + id: execution_id, + status: "queued".to_string(), + response: None, + }); + + // 异步执行代码 + tokio::spawn(async move { + // 更新状态为“正在编译” + let mut status_map = EXECUTION_STATUS.lock().unwrap(); + if let Some(status) = status_map.get_mut(&execution_id) { + status.status = "compiling".to_string(); + } + + let response = match execute_code(code, language, execution_id).await { + Ok(response) => Some(response), + Err(e) => { + error!("Execution failed: {}", e); + None + } + }; + + // 更新执行状态 + let mut status_map = EXECUTION_STATUS.lock().unwrap(); + if let Some(status) = status_map.get_mut(&execution_id) { + status.status = "completed".to_string(); + status.response = response; + } + }); + + // 返回初始状态 + Ok(Json(ExecutionStatus { + id: execution_id, + status: "queued".to_string(), + response: None, + })) +} + +#[get("/api/v1/status/")] +async fn get_execution_status(id: Uuid) -> Json { + let status_map = EXECUTION_STATUS.lock().unwrap(); + if let Some(status) = status_map.get(&id) { + Json(status.clone()) + } else { + Json(ExecutionStatus { + id, + status: "not found".to_string(), + response: None, + }) + } +} + +#[get("/api/v1/result/")] +async fn get_execution_result(id: Uuid) -> Json { + let status_map = EXECUTION_STATUS.lock().unwrap(); + if let Some(status) = status_map.get(&id) { + if let Some(response) = &status.response { + Json(response.clone()) + } else { + Json(CodeResponse { + stdout: "".to_string(), + stderr: "Result not available".to_string(), + returncode: -1, + }) + } + } else { + Json(CodeResponse { + stdout: "".to_string(), + stderr: "Execution ID not found".to_string(), + returncode: -1, + }) + } +} + +#[launch] +fn rocket() -> _ { + rocket::build() + .mount("/", routes![handle_execute_code, get_execution_status, get_execution_result]) +} \ No newline at end of file diff --git a/online_compiler/docker-compose.yml b/online_compiler/docker-compose.yml new file mode 100644 index 0000000..7c94d85 --- /dev/null +++ b/online_compiler/docker-compose.yml @@ -0,0 +1,24 @@ +version: '3' +services: + api: + build: + context: . + dockerfile: Dockerfile.api + ports: + - "8000:8000" + networks: + - app-network + + web: + build: + context: . + dockerfile: Dockerfile.web + ports: + - "8001:8001" + networks: + - app-network + depends_on: + - api + +networks: + app-network: \ No newline at end of file diff --git a/online_compiler/web/.gitignore b/online_compiler/web/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/online_compiler/web/.gitignore @@ -0,0 +1 @@ +/target diff --git a/online_compiler/web/Cargo.toml b/online_compiler/web/Cargo.toml new file mode 100644 index 0000000..9746dfe --- /dev/null +++ b/online_compiler/web/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "online_compiler_web" +version = "0.1.0" +edition = "2021" + +[dependencies] +rocket = { version = "0.5", features = ["json"] } +rocket_contrib = { version = "0.4.10", features = ["serve"] } +rocket_cors = "0.5" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +reqwest = { version = "0.12", features = ["json"] } \ No newline at end of file diff --git a/online_compiler/web/src/main.rs b/online_compiler/web/src/main.rs new file mode 100644 index 0000000..de01d14 --- /dev/null +++ b/online_compiler/web/src/main.rs @@ -0,0 +1,145 @@ +#[macro_use] extern crate rocket; +#[macro_use] extern crate rocket_contrib; + +use rocket::response::content::Html; +use rocket_contrib::serve::StaticFiles; +use rocket_cors::{AllowedOrigins, CorsOptions}; +use rocket::State; +use rocket::request::Form; +use rocket::http::Status; +use serde_json::{json, Value}; +use reqwest::Client; +use std::sync::Mutex; + +// 用于存储API客户端 +struct ApiClient { + client: Client, +} + +impl ApiClient { + fn new() -> Self { + ApiClient { + client: Client::new(), + } + } + + async fn execute_code(&self, code: &str, language: &str) -> Result { + let url = "http://api:8000/api/v1/execute"; // 使用Docker网络中的服务名 + let body = json!({ + "code": code, + "language": language + }); + + let response = self.client.post(url) + .json(&body) + .send() + .await + .map_err(|e| e.to_string())?; + + if response.status().is_success() { + response.json::().await.map_err(|e| e.to_string()) + } else { + Err("API request failed".to_string()) + } + } + + async fn get_status(&self, id: &str) -> Result { + let url = format!("http://api:8000/api/v1/status/{}", id); + let response = self.client.get(&url) + .send() + .await + .map_err(|e| e.to_string())?; + + if response.status().is_success() { + response.json::().await.map_err(|e| e.to_string()) + } else { + Err("API request failed".to_string()) + } + } +} + +#[get("/")] +fn index() -> Html<&'static str> { + Html(r#" + + + + + + 在线编译器 + + + + +
+

在线编译器

+
+ + + +
+
+
+

+        
+
+ + + +"#) +} + +#[post("/run", data = "
")] +async fn run_code(form: Form, api_client: State>) -> Result, Status> { + let form_data = form.into_inner(); + let code = &form_data.code; + let language = &form_data.language; + + let api_client = api_client.lock().unwrap(); + match api_client.execute_code(code, language).await { + Ok(response) => Ok(rocket::response::Json(response)), + Err(e) => { + error!("API call failed: {}", e); + Err(Status::InternalServerError) + } + } +} + +#[get("/api/v1/status/")] +async fn get_execution_status(id: String, api_client: State>) -> Result, Status> { + let api_client = api_client.lock().unwrap(); + match api_client.get_status(&id).await { + Ok(status) => Ok(rocket::response::Json(status)), + Err(e) => { + error!("API call failed: {}", e); + Err(Status::InternalServerError) + } + } +} + +#[derive(FromForm)] +struct CodeForm { + code: String, + language: String, +} + +#[launch] +fn rocket() -> _ { + let cors = CorsOptions::default() + .allowed_origins(AllowedOrigins::all()) + .to_cors().unwrap(); + + rocket::build() + .mount("/", routes![index]) + .mount("/static", StaticFiles::from("static/")) + .manage(Mutex::new(ApiClient::new())) + .mount("/run", routes![run_code]) + .mount("/api/v1/status", routes![get_execution_status]) + .attach(cors) + .port(8001) // 在这里指定监听 8001 端口 +} \ No newline at end of file diff --git a/online_compiler/web/static/index.html b/online_compiler/web/static/index.html new file mode 100644 index 0000000..1f25b5d --- /dev/null +++ b/online_compiler/web/static/index.html @@ -0,0 +1,33 @@ + + + + + + 在线编译器 + + + + +
+

在线编译器

+
+
+ + +
+ + +
+
+
+

+        
+
+ + + \ No newline at end of file diff --git a/online_compiler/web/static/scripts.js b/online_compiler/web/static/scripts.js new file mode 100644 index 0000000..e864c20 --- /dev/null +++ b/online_compiler/web/static/scripts.js @@ -0,0 +1,53 @@ +$(document).ready(function() { + $('#run-button').on('click', function() { + const code = $('#code').val(); + const language = $('#language').val(); + + // 初始化状态 + $('#status').text('排队中...'); + $('#output').text(''); + + $.ajax({ + url: '/run', + method: 'POST', + contentType: 'application/x-www-form-urlencoded; charset=UTF-8', + data: { code, language }, + success: function(response) { + const executionId = response.id; + pollForStatus(executionId); + }, + error: function(error) { + console.error('Error:', error); + $('#status').text('请求失败'); + $('#output').text('无法连接到服务器,请稍后再试。'); + } + }); + }); + + function pollForStatus(executionId) { + const interval = setInterval(() => { + $.ajax({ + url: `/api/v1/status/${executionId}`, + method: 'GET', + success: function(response) { + $('#status').text(`状态: ${response.status}`); + if (response.status === 'completed') { + clearInterval(interval); + if (response.response) { + $('#output').text(`输出:\n${response.response.stdout}\n\n错误:\n${response.response.stderr}`); + } else { + $('#output').text('结果不可用。'); + } + } else if (response.status === 'compiling' || response.status === 'running') { + $('#status').text(`状态: ${response.status}`); + } + }, + error: function(error) { + console.error('Error:', error); + $('#status').text('请求失败'); + $('#output').text('无法连接到服务器,请稍后再试。'); + } + }); + }, 1000); // 每秒轮询一次 + } +}); \ No newline at end of file diff --git a/online_compiler/web/static/styles.css b/online_compiler/web/static/styles.css new file mode 100644 index 0000000..38f64c3 --- /dev/null +++ b/online_compiler/web/static/styles.css @@ -0,0 +1,55 @@ +body { + font-family: Arial, sans-serif; + background-color: #f4f4f4; + margin: 0; + padding: 0; +} + +.container { + max-width: 800px; + margin: 50px auto; + padding: 20px; + background-color: #fff; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + border-radius: 5px; +} + +.editor-container, .output-container { + margin-bottom: 20px; +} + +.language-selector { + display: flex; + align-items: center; + margin-bottom: 10px; +} + +.language-selector label { + margin-right: 10px; +} + +textarea { + width: 100%; + height: 200px; + padding: 10px; + font-size: 14px; + border: 1px solid #ddd; + border-radius: 5px; +} + +select, button { + padding: 10px; + font-size: 14px; + border: 1px solid #ddd; + border-radius: 5px; + cursor: pointer; +} + +.output-container pre { + white-space: pre-wrap; + word-wrap: break-word; + background-color: #f9f9f9; + padding: 10px; + border: 1px solid #ddd; + border-radius: 5px; +} \ No newline at end of file diff --git a/online_runer/REDME. md b/online_runer/REDME. md new file mode 100644 index 0000000..9b9a0a0 --- /dev/null +++ b/online_runer/REDME. md @@ -0,0 +1,145 @@ + +## 安装与运行 + +### 前提条件 + +- 安装 [Rust](https://www.rust-lang.org/tools/install) +- 安装 [Docker](https://docs.docker.com/get-docker/) +- 安装 [Docker Compose](https://docs.docker.com/compose/install/) + +### 构建Docker镜像 + +你说得对,为了使在线编译器API能够正常工作,我们需要确保依赖的Docker镜像环境已经构建好并推送到Docker Hub。这些镜像将用于执行不同语言的代码。 +1. 构建和推送Docker镜像 + +首先,我们需要为每种编程语言创建一个Docker镜像,并将其推送到Docker Hub。假设你已经有了Docker Hub账号,以下是每种语言的Dockerfile示例: +Python Runner Dockerfile (python-runner/Dockerfile) + +dockerfile +深色版本 + +FROM python:3.9-slim + +# 设置工作目录 +WORKDIR /code + +# 安装必要的包 +RUN pip install --no-cache-dir -q flake8 + +# 默认命令 +CMD ["python", "-"] + +Rust Runner Dockerfile (rust-runner/Dockerfile) + +dockerfile +深色版本 + +FROM rust:latest + +# 设置工作目录 +WORKDIR /code + +# 默认命令 +CMD ["rustc", "-", "-o", "/code/a.out" && "./a.out"] + +Nim Runner Dockerfile (nim-runner/Dockerfile) + +dockerfile +深色版本 + +FROM nimlang/nim:latest + +# 设置工作目录 +WORKDIR /code + +# 默认命令 +CMD ["nim", "compile", "-", "&&", "./a.out"] + +Lua Runner Dockerfile (lua-runner/Dockerfile) + +dockerfile +深色版本 + +FROM lua:5.4 + +# 设置工作目录 +WORKDIR /code + +# 默认命令 +CMD ["lua", "-"] + +2. 构建并推送Docker镜像 + +对于每个Dockerfile,你需要在相应的目录中运行以下命令来构建和推送镜像到Docker Hub。请确保你已经登录到Docker Hub。 +构建并推送Python Runner镜像 + +sh +深色版本 + +cd python-runner +docker build -t your_dockerhub_username/python-runner . +docker push your_dockerhub_username/python-runner + +构建并推送Rust Runner镜像 + +sh +深色版本 + +cd rust-runner +docker build -t your_dockerhub_username/rust-runner . +docker push your_dockerhub_username/rust-runner + +构建并推送Nim Runner镜像 + +sh +深色版本 + +cd nim-runner +docker build -t your_dockerhub_username/nim-runner . +docker push your_dockerhub_username/nim-runner + +构建并推送Lua Runner镜像 + +sh +深色版本 + +cd lua-runner +docker build -t your_dockerhub_username/lua-runner . +docker push your_dockerhub_username/lua-runner + + + + + + + + +1. 构建并推送每种语言的执行环境到Docker Hub: + - Python Runner: + ```sh + cd python-runner + docker build -t your_dockerhub_username/python-runner . + docker push your_dockerhub_username/python-runner + ``` + - Rust Runner: + ```sh + cd rust-runner + docker build -t your_dockerhub_username/rust-runner . + docker push your_dockerhub_username/rust-runner + ``` + - Nim Runner: + ```sh + cd nim-runner + docker build -t your_dockerhub_username/nim-runner . + docker push your_dockerhub_username/nim-runner + ``` + - Lua Runner: + ```sh + cd lua-runner + docker build -t your_dockerhub_username/lua-runner . + docker push your_dockerhub_username/lua-runner + ``` + +2. 构建主项目Docker镜像: + ```sh + docker-compose build \ No newline at end of file diff --git a/online_runer/lua-runner/Dockerfile b/online_runer/lua-runner/Dockerfile new file mode 100644 index 0000000..75ff6fd --- /dev/null +++ b/online_runer/lua-runner/Dockerfile @@ -0,0 +1,7 @@ +FROM lua:5.4 + +# 设置工作目录 +WORKDIR /code + +# 默认命令 +CMD ["lua", "-"] \ No newline at end of file diff --git a/online_runer/nim-runner/Dockerfile b/online_runer/nim-runner/Dockerfile new file mode 100644 index 0000000..5b85bdd --- /dev/null +++ b/online_runer/nim-runner/Dockerfile @@ -0,0 +1,7 @@ +FROM nimlang/nim:latest + +# 设置工作目录 +WORKDIR /code + +# 默认命令 +CMD ["nim", "compile", "-", "&&", "./a.out"] \ No newline at end of file diff --git a/online_runer/python-runner/Dockerfile b/online_runer/python-runner/Dockerfile new file mode 100644 index 0000000..45e2d14 --- /dev/null +++ b/online_runer/python-runner/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.9-slim + +# 设置工作目录 +WORKDIR /code + +# 安装必要的包 +RUN pip install --no-cache-dir -q flake8 + +# 默认命令 +CMD ["python", "-"] \ No newline at end of file diff --git a/online_runer/rust-runner/Dockerfile b/online_runer/rust-runner/Dockerfile new file mode 100644 index 0000000..205eeff --- /dev/null +++ b/online_runer/rust-runner/Dockerfile @@ -0,0 +1,7 @@ +FROM rust:latest + +# 设置工作目录 +WORKDIR /code + +# 默认命令 +CMD ["rustc", "-", "-o", "/code/a.out" && "./a.out"] \ No newline at end of file