Enhance Docker integration and API for container management

- Implemented Docker container scanning and periodic updates in the Server initialization.
- Added new RPC endpoints for managing Docker containers, including start, stop, and restart functionalities.
- Updated the API to handle package management for Docker-based applications.
- Improved environment variable handling for user-specific configurations in Podman and Docker clients.
- Enhanced the development startup script to include Docker container management and provide clearer instructions for full stack setup.
This commit is contained in:
Dorian
2026-01-27 23:21:26 +00:00
parent 3b3f70276f
commit 30ed48ad1b
17 changed files with 2076 additions and 20 deletions

View File

@@ -73,6 +73,8 @@ impl RpcHandler {
"server.echo" => self.handle_echo(rpc_req.params).await,
"auth.login" => self.handle_auth_login(rpc_req.params).await,
"auth.logout" => self.handle_auth_logout().await,
// Container orchestration (for Archipelago-managed containers)
"container-install" => self.handle_container_install(rpc_req.params).await,
"container-start" => self.handle_container_start(rpc_req.params).await,
"container-stop" => self.handle_container_stop(rpc_req.params).await,
@@ -81,6 +83,12 @@ impl RpcHandler {
"container-status" => self.handle_container_status(rpc_req.params).await,
"container-logs" => self.handle_container_logs(rpc_req.params).await,
"container-health" => self.handle_container_health(rpc_req.params).await,
// Package management (for docker-compose apps)
"package.start" => self.handle_package_start(rpc_req.params).await,
"package.stop" => self.handle_package_stop(rpc_req.params).await,
"package.restart" => self.handle_package_restart(rpc_req.params).await,
_ => {
Err(anyhow::anyhow!("Unknown method: {}", rpc_req.method))
}
@@ -373,4 +381,92 @@ impl RpcHandler {
Ok(serde_json::Value::Object(health_map))
}
// Package management methods for docker-compose containers
async fn handle_package_start(
&self,
params: Option<serde_json::Value>,
) -> Result<serde_json::Value> {
let params = params.ok_or_else(|| anyhow::anyhow!("Missing params"))?;
let package_id = params
.get("id")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing package id"))?;
// Convert package ID to container name (e.g., "bitcoin" -> "archy-bitcoin")
let container_name = format!("archy-{}", package_id);
// Use docker CLI to start the container
let output = tokio::process::Command::new("docker")
.arg("start")
.arg(&container_name)
.output()
.await
.context("Failed to execute docker start")?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(anyhow::anyhow!("Failed to start container: {}", stderr));
}
Ok(serde_json::Value::Null)
}
async fn handle_package_stop(
&self,
params: Option<serde_json::Value>,
) -> Result<serde_json::Value> {
let params = params.ok_or_else(|| anyhow::anyhow!("Missing params"))?;
let package_id = params
.get("id")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing package id"))?;
// Convert package ID to container name
let container_name = format!("archy-{}", package_id);
// Use docker CLI to stop the container
let output = tokio::process::Command::new("docker")
.arg("stop")
.arg(&container_name)
.output()
.await
.context("Failed to execute docker stop")?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(anyhow::anyhow!("Failed to stop container: {}", stderr));
}
Ok(serde_json::Value::Null)
}
async fn handle_package_restart(
&self,
params: Option<serde_json::Value>,
) -> Result<serde_json::Value> {
let params = params.ok_or_else(|| anyhow::anyhow!("Missing params"))?;
let package_id = params
.get("id")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing package id"))?;
// Convert package ID to container name
let container_name = format!("archy-{}", package_id);
// Use docker CLI to restart the container
let output = tokio::process::Command::new("docker")
.arg("restart")
.arg(&container_name)
.output()
.await
.context("Failed to execute docker restart")?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(anyhow::anyhow!("Failed to restart container: {}", stderr));
}
Ok(serde_json::Value::Null)
}
}