Skip to content

Commit b9ec333

Browse files
committed
feat: Add support for Docker Desktop socket locations on macOS
Docker Desktop for macOS v4.x+ changed the default socket location from /var/run/docker.sock to ~/.docker/run/docker.sock. This caused ConnectionError/FileNotFoundError when users didn't have DOCKER_HOST set. This commit adds automatic socket discovery that checks multiple locations in order of preference: 1. /var/run/docker.sock (traditional Linux/macOS location) 2. ~/.docker/run/docker.sock (Docker Desktop v4.x+ on macOS) 3. ~/.docker/desktop/docker.sock (older Docker Desktop location) The implementation: - Adds UNIX_SOCKET_PATHS list with known socket locations - Adds _find_available_unix_socket() function for discovery - Makes DEFAULT_UNIX_SOCKET dynamically computed at import time - Falls back to /var/run/docker.sock if no socket exists This only affects Unix/macOS; Windows continues to use named pipes. DOCKER_HOST environment variable and Docker contexts still take precedence. Fixes #3271
1 parent df3f8e2 commit b9ec333

3 files changed

Lines changed: 252 additions & 247 deletions

File tree

docker/constants.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
import sys
23

34
from .version import __version__
@@ -11,7 +12,26 @@
1112
]
1213

1314
DEFAULT_HTTP_HOST = "127.0.0.1"
14-
DEFAULT_UNIX_SOCKET = "http+unix:///var/run/docker.sock"
15+
16+
# Potential Unix socket locations in order of preference
17+
UNIX_SOCKET_PATHS = [
18+
'/var/run/docker.sock', # Traditional Linux/macOS location
19+
os.path.expanduser('~/.docker/run/docker.sock'), # Docker Desktop v4.x+ on macOS
20+
os.path.expanduser('~/.docker/desktop/docker.sock'), # Older Docker Desktop location
21+
]
22+
23+
24+
def _find_available_unix_socket():
25+
"""Find the first available Docker socket from known locations."""
26+
for path in UNIX_SOCKET_PATHS:
27+
if os.path.exists(path):
28+
return f"http+unix://{path}"
29+
# Fallback to traditional location even if it doesn't exist
30+
return f"http+unix://{UNIX_SOCKET_PATHS[0]}"
31+
32+
33+
# Dynamic default socket - checks multiple locations
34+
DEFAULT_UNIX_SOCKET = _find_available_unix_socket()
1535
DEFAULT_NPIPE = 'npipe:////./pipe/docker_engine'
1636

1737
BYTE_UNITS = {

tests/unit/client_test.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
DEFAULT_DOCKER_API_VERSION,
1111
DEFAULT_MAX_POOL_SIZE,
1212
DEFAULT_TIMEOUT_SECONDS,
13+
DEFAULT_UNIX_SOCKET,
1314
IS_WINDOWS_PLATFORM,
1415
)
1516
from docker.utils import kwargs_from_env
@@ -89,9 +90,11 @@ def test_default_pool_size_unix(self, mock_obj):
8990
client.ping()
9091

9192
base_url = f"{client.api.base_url}/v{client.api._version}/_ping"
93+
# Extract socket path from DEFAULT_UNIX_SOCKET (remove http+unix:// prefix)
94+
socket_path = DEFAULT_UNIX_SOCKET.replace('http+unix://', '')
9295

9396
mock_obj.assert_called_once_with(base_url,
94-
"/var/run/docker.sock",
97+
socket_path,
9598
60,
9699
maxsize=DEFAULT_MAX_POOL_SIZE
97100
)
@@ -125,9 +128,11 @@ def test_pool_size_unix(self, mock_obj):
125128
client.ping()
126129

127130
base_url = f"{client.api.base_url}/v{client.api._version}/_ping"
131+
# Extract socket path from DEFAULT_UNIX_SOCKET (remove http+unix:// prefix)
132+
socket_path = DEFAULT_UNIX_SOCKET.replace('http+unix://', '')
128133

129134
mock_obj.assert_called_once_with(base_url,
130-
"/var/run/docker.sock",
135+
socket_path,
131136
60,
132137
maxsize=POOL_SIZE
133138
)
@@ -198,9 +203,11 @@ def test_default_pool_size_from_env_unix(self, mock_obj):
198203
client.ping()
199204

200205
base_url = f"{client.api.base_url}/v{client.api._version}/_ping"
206+
# Extract socket path from DEFAULT_UNIX_SOCKET (remove http+unix:// prefix)
207+
socket_path = DEFAULT_UNIX_SOCKET.replace('http+unix://', '')
201208

202209
mock_obj.assert_called_once_with(base_url,
203-
"/var/run/docker.sock",
210+
socket_path,
204211
60,
205212
maxsize=DEFAULT_MAX_POOL_SIZE
206213
)
@@ -233,9 +240,11 @@ def test_pool_size_from_env_unix(self, mock_obj):
233240
client.ping()
234241

235242
base_url = f"{client.api.base_url}/v{client.api._version}/_ping"
243+
# Extract socket path from DEFAULT_UNIX_SOCKET (remove http+unix:// prefix)
244+
socket_path = DEFAULT_UNIX_SOCKET.replace('http+unix://', '')
236245

237246
mock_obj.assert_called_once_with(base_url,
238-
"/var/run/docker.sock",
247+
socket_path,
239248
60,
240249
maxsize=POOL_SIZE
241250
)

0 commit comments

Comments
 (0)