Skip to content

Commit 3b98b67

Browse files
committed
fix(bootstrap): auto-detect Docker Desktop socket on macOS
Add ~/Library/Containers/com.docker.docker/Data/docker-cli.sock to the alternative socket probe list. Recent Docker Desktop versions on macOS may not create /var/run/docker.sock, causing gateway start to fail with a misleading connection error. When the default socket is unreachable, check_docker_available() now iterates alternative sockets and connects through the first one that responds to a ping, instead of failing immediately. Closes #443 Signed-off-by: Serge Panev <spanev@nvidia.com>
1 parent dcd9912 commit 3b98b67

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

crates/openshell-bootstrap/src/docker.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ pub struct DockerPreflight {
107107
/// - `/var/run/docker.sock` — default for Docker Desktop, `OrbStack`, Colima
108108
/// - `$HOME/.colima/docker.sock` — Colima (older installs)
109109
/// - `$HOME/.orbstack/run/docker.sock` — `OrbStack` (if symlink is missing)
110+
/// - `$HOME/Library/Containers/com.docker.docker/Data/docker-cli.sock` — Docker Desktop on macOS
111+
/// (recent versions may not create `/var/run/docker.sock`)
110112
const WELL_KNOWN_SOCKET_PATHS: &[&str] = &[
111113
"/var/run/docker.sock",
112114
// Expanded at runtime via home_dir():
@@ -125,6 +127,10 @@ pub async fn check_docker_available() -> Result<DockerPreflight> {
125127
let docker = match Docker::connect_with_local_defaults() {
126128
Ok(d) => d,
127129
Err(err) => {
130+
// Default connection failed — try alternative sockets before giving up.
131+
if let Some(preflight) = try_alternative_sockets().await {
132+
return Ok(preflight);
133+
}
128134
return Err(docker_not_reachable_error(
129135
&format!("{err}"),
130136
"Failed to create Docker client",
@@ -134,6 +140,10 @@ pub async fn check_docker_available() -> Result<DockerPreflight> {
134140

135141
// Step 2: Ping the daemon to confirm it's responsive.
136142
if let Err(err) = docker.ping().await {
143+
// Ping failed — try alternative sockets before giving up.
144+
if let Some(preflight) = try_alternative_sockets().await {
145+
return Ok(preflight);
146+
}
137147
return Err(docker_not_reachable_error(
138148
&format!("{err}"),
139149
"Docker socket exists but the daemon is not responding",
@@ -149,6 +159,25 @@ pub async fn check_docker_available() -> Result<DockerPreflight> {
149159
Ok(DockerPreflight { docker, version })
150160
}
151161

162+
/// Try connecting to Docker through alternative socket paths.
163+
///
164+
/// Returns `Some(DockerPreflight)` if a working socket was found.
165+
async fn try_alternative_sockets() -> Option<DockerPreflight> {
166+
for path in find_alternative_sockets() {
167+
let socket_url = format!("unix://{path}");
168+
let docker = match Docker::connect_with_socket(&socket_url, 120, API_DEFAULT_VERSION) {
169+
Ok(d) => d,
170+
Err(_) => continue,
171+
};
172+
if docker.ping().await.is_ok() {
173+
let version = docker.version().await.ok().and_then(|v| v.version);
174+
eprintln!("→ Connected to Docker via alternative socket: {path}");
175+
return Some(DockerPreflight { docker, version });
176+
}
177+
}
178+
None
179+
}
180+
152181
/// Build a rich, user-friendly error when Docker is not reachable.
153182
fn docker_not_reachable_error(raw_err: &str, summary: &str) -> miette::Report {
154183
let docker_host = std::env::var("DOCKER_HOST").ok();
@@ -221,6 +250,7 @@ fn find_alternative_sockets() -> Vec<String> {
221250
let home_sockets = [
222251
format!("{home}/.colima/docker.sock"),
223252
format!("{home}/.orbstack/run/docker.sock"),
253+
format!("{home}/Library/Containers/com.docker.docker/Data/docker-cli.sock"),
224254
];
225255
for path in &home_sockets {
226256
if std::path::Path::new(path).exists() && !found.contains(path) {

0 commit comments

Comments
 (0)