@@ -107,11 +107,13 @@ 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
110111const WELL_KNOWN_SOCKET_PATHS : & [ & str ] = & [
111112 "/var/run/docker.sock" ,
112113 // Expanded at runtime via home_dir():
113114 // ~/.colima/docker.sock
114115 // ~/.orbstack/run/docker.sock
116+ // ~/Library/Containers/com.docker.docker/Data/docker-cli.sock
115117] ;
116118
117119/// Check that a Docker-compatible runtime is installed, running, and reachable.
@@ -120,11 +122,18 @@ const WELL_KNOWN_SOCKET_PATHS: &[&str] = &[
120122/// deploy work begins. On failure it produces a user-friendly error with
121123/// actionable recovery steps instead of a raw bollard connection error.
122124pub async fn check_docker_available ( ) -> Result < DockerPreflight > {
125+ if let Some ( preflight) = try_alternative_sockets ( None ) . await {
126+ return Ok ( preflight) ;
127+ }
128+
123129 // Step 1: Try to connect using bollard's default resolution
124130 // (respects DOCKER_HOST, then falls back to /var/run/docker.sock).
125131 let docker = match Docker :: connect_with_local_defaults ( ) {
126132 Ok ( d) => d,
127133 Err ( err) => {
134+ if let Some ( preflight) = try_alternative_sockets ( None ) . await {
135+ return Ok ( preflight) ;
136+ }
128137 return Err ( docker_not_reachable_error (
129138 & format ! ( "{err}" ) ,
130139 "Failed to create Docker client" ,
@@ -134,6 +143,9 @@ pub async fn check_docker_available() -> Result<DockerPreflight> {
134143
135144 // Step 2: Ping the daemon to confirm it's responsive.
136145 if let Err ( err) = docker. ping ( ) . await {
146+ if let Some ( preflight) = try_alternative_sockets ( Some ( "/var/run/docker.sock" ) ) . await {
147+ return Ok ( preflight) ;
148+ }
137149 return Err ( docker_not_reachable_error (
138150 & format ! ( "{err}" ) ,
139151 "Docker socket exists but the daemon is not responding" ,
@@ -149,6 +161,30 @@ pub async fn check_docker_available() -> Result<DockerPreflight> {
149161 Ok ( DockerPreflight { docker, version } )
150162}
151163
164+ async fn try_alternative_sockets ( skip_path : Option < & str > ) -> Option < DockerPreflight > {
165+ if env_non_empty ( "DOCKER_HOST" ) . is_some ( ) {
166+ return None ;
167+ }
168+
169+ for path in find_alternative_sockets ( ) {
170+ if skip_path. is_some_and ( |skip| skip == path) {
171+ continue ;
172+ }
173+
174+ let Ok ( docker) = Docker :: connect_with_socket ( & path, 120 , API_DEFAULT_VERSION ) else {
175+ continue ;
176+ } ;
177+ if docker. ping ( ) . await . is_err ( ) {
178+ continue ;
179+ }
180+
181+ let version = docker. version ( ) . await . ok ( ) . and_then ( |v| v. version ) ;
182+ return Some ( DockerPreflight { docker, version } ) ;
183+ }
184+
185+ None
186+ }
187+
152188/// Build a rich, user-friendly error when Docker is not reachable.
153189fn docker_not_reachable_error ( raw_err : & str , summary : & str ) -> miette:: Report {
154190 let docker_host = std:: env:: var ( "DOCKER_HOST" ) . ok ( ) ;
@@ -218,10 +254,7 @@ fn find_alternative_sockets() -> Vec<String> {
218254
219255 // Check home-relative paths
220256 if let Some ( home) = home_dir ( ) {
221- let home_sockets = [
222- format ! ( "{home}/.colima/docker.sock" ) ,
223- format ! ( "{home}/.orbstack/run/docker.sock" ) ,
224- ] ;
257+ let home_sockets = home_relative_socket_paths ( & home) ;
225258 for path in & home_sockets {
226259 if std:: path:: Path :: new ( path) . exists ( ) && !found. contains ( path) {
227260 found. push ( path. clone ( ) ) ;
@@ -236,6 +269,14 @@ fn home_dir() -> Option<String> {
236269 std:: env:: var ( "HOME" ) . ok ( )
237270}
238271
272+ fn home_relative_socket_paths ( home : & str ) -> Vec < String > {
273+ vec ! [
274+ format!( "{home}/.colima/docker.sock" ) ,
275+ format!( "{home}/.orbstack/run/docker.sock" ) ,
276+ format!( "{home}/Library/Containers/com.docker.docker/Data/docker-cli.sock" ) ,
277+ ]
278+ }
279+
239280/// Create an SSH Docker client from remote options.
240281pub async fn create_ssh_docker_client ( remote : & RemoteOptions ) -> Result < Docker > {
241282 // Ensure destination has ssh:// prefix
@@ -1195,4 +1236,17 @@ mod tests {
11951236 "should return a reasonable number of sockets"
11961237 ) ;
11971238 }
1239+
1240+ #[ test]
1241+ fn home_relative_socket_paths_include_docker_desktop_socket ( ) {
1242+ let home = "/tmp/test-home" ;
1243+ let sockets = home_relative_socket_paths ( home) ;
1244+
1245+ assert ! (
1246+ sockets. contains( & format!(
1247+ "{home}/Library/Containers/com.docker.docker/Data/docker-cli.sock"
1248+ ) ) ,
1249+ "should probe Docker Desktop's macOS socket path"
1250+ ) ;
1251+ }
11981252}
0 commit comments