kittynode_core/application/
start_docker.rs

1use eyre::{Result, eyre};
2use std::process::Command;
3use tracing::{error, info};
4
5#[cfg(target_os = "windows")]
6use std::path::Path;
7
8pub async fn start_docker() -> Result<()> {
9    info!("Attempting to start Docker Desktop");
10
11    #[cfg(target_os = "macos")]
12    {
13        Command::new("open")
14            .arg("-a")
15            .arg("Docker")
16            .spawn()
17            .map_err(|e| {
18                error!("Failed to start Docker Desktop on macOS: {}", e);
19                eyre!("Failed to start Docker Desktop: {}. Please ensure Docker Desktop is installed.", e)
20            })?;
21        info!("Docker Desktop start command sent on macOS");
22    }
23
24    #[cfg(target_os = "linux")]
25    {
26        let mut started = false;
27
28        // Try different installation methods
29        let attempts = [
30            // System service
31            ("systemctl", vec!["start", "docker-desktop"]),
32            // User service
33            ("systemctl", vec!["--user", "start", "docker-desktop"]),
34            // Flatpak
35            ("flatpak", vec!["run", "com.docker.DockerDesktop"]),
36            // Direct binary in common locations
37            ("docker-desktop", vec![]),
38            ("/usr/bin/docker-desktop", vec![]),
39            ("/opt/docker-desktop/docker-desktop", vec![]),
40        ];
41
42        for (cmd, args) in attempts {
43            if Command::new(cmd).args(&args).spawn().is_ok() {
44                info!("Started Docker Desktop using: {} {:?}", cmd, args);
45                started = true;
46                break;
47            }
48        }
49
50        if !started {
51            error!("Failed to start Docker Desktop on Linux after trying all methods");
52            return Err(eyre!(
53                "Failed to start Docker Desktop. Please ensure Docker Desktop is installed and try starting it manually."
54            ));
55        }
56    }
57
58    #[cfg(target_os = "windows")]
59    {
60        let mut started = false;
61
62        // Try common installation paths first (more reliable than PATH check)
63        let common_paths = [
64            "C:\\Program Files\\Docker\\Docker\\Docker Desktop.exe",
65            "C:\\Program Files (x86)\\Docker\\Docker\\Docker Desktop.exe",
66            "%LOCALAPPDATA%\\Docker\\Docker Desktop.exe",
67        ];
68
69        for path in common_paths {
70            let expanded_path = if path.contains('%') {
71                // Expand environment variables
72                std::env::var("LOCALAPPDATA")
73                    .ok()
74                    .map(|appdata| path.replace("%LOCALAPPDATA%", &appdata))
75                    .unwrap_or_else(|| path.to_string())
76            } else {
77                path.to_string()
78            };
79
80            if Path::new(&expanded_path).exists() {
81                if Command::new("cmd")
82                    .args(&["/C", "start", "", &expanded_path])
83                    .spawn()
84                    .is_ok()
85                {
86                    started = true;
87                    info!("Started Docker Desktop from: {}", expanded_path);
88                    break;
89                }
90            }
91        }
92
93        // Only try PATH as a last resort with a check for existence
94        if !started {
95            // Use 'where' command to check if Docker Desktop.exe is in PATH
96            if let Ok(output) = Command::new("where").arg("Docker Desktop.exe").output() {
97                if output.status.success() {
98                    if Command::new("cmd")
99                        .args(&["/C", "start", "", "Docker Desktop.exe"])
100                        .spawn()
101                        .is_ok()
102                    {
103                        started = true;
104                        info!("Started Docker Desktop using PATH");
105                    }
106                }
107            }
108        }
109
110        if !started {
111            error!("Failed to start Docker Desktop on Windows");
112            return Err(eyre!(
113                "Failed to start Docker Desktop. Please ensure Docker Desktop is installed and try starting it manually."
114            ));
115        }
116    }
117
118    Ok(())
119}