feat: Add support for Docker Desktop socket locations on macOS#3378
feat: Add support for Docker Desktop socket locations on macOS#3378halicki wants to merge 3 commits intodocker:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the default Unix socket handling to automatically discover Docker Desktop’s macOS socket locations while keeping existing behavior on other platforms, and aligns tests with the new dynamic default.
Changes:
- Introduced
UNIX_SOCKET_PATHSand_find_available_unix_socket()indocker/constants.pysoDEFAULT_UNIX_SOCKETprefers/var/run/docker.sock, then~/.docker/run/docker.sock, then~/.docker/desktop/docker.sock, falling back to/var/run/docker.sockif none exist. - Updated client connection pool tests in
tests/unit/client_test.pyto derive the Unix socket path fromDEFAULT_UNIX_SOCKETinstead of hard-coding/var/run/docker.sock, making them resilient to environment-specific socket paths. - Updated
tests/unit/utils_test.pyto (a) useDEFAULT_UNIX_SOCKETinparse_hostdefault-host tests and (b) add coverage for the"unix://"empty-path case, along with consistent string style cleanups.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
docker/constants.py |
Adds environment-aware Unix socket discovery and makes DEFAULT_UNIX_SOCKET dynamic based on known Docker socket locations. |
tests/unit/client_test.py |
Adjusts Unix connection pool tests to use DEFAULT_UNIX_SOCKET-derived paths instead of a hard-coded /var/run/docker.sock. |
tests/unit/utils_test.py |
Aligns parse_host tests with the dynamic DEFAULT_UNIX_SOCKET, adds a specific test for "unix://" fallback, and performs minor test style updates. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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 docker#3271 Signed-off-by: Arkadiusz Halicki <halicki.arkadiusz@gmail.com>
Add UnixSocketDiscoveryTest class with tests that mock os.path.exists to verify socket selection behavior: - test_find_socket_prefers_traditional_location: /var/run/docker.sock preferred - test_find_socket_falls_back_to_docker_desktop: ~/.docker/run/docker.sock used - test_find_socket_falls_back_to_older_docker_desktop: ~/.docker/desktop/docker.sock used - test_find_socket_fallback_when_none_exist: Falls back to traditional location - test_find_socket_preference_order: Verifies v4 > older desktop ordering - test_unix_socket_paths_order: Verifies UNIX_SOCKET_PATHS constant Signed-off-by: Arkadiusz Halicki <halicki.arkadiusz@gmail.com>
- Move imports to top level (mock, UNIX_SOCKET_PATHS, _find_available_unix_socket) - Remove unused imports inside test methods - Format mock.patch calls to follow line length conventions Signed-off-by: Arkadiusz Halicki <halicki.arkadiusz@gmail.com>
d147fc6 to
43bf0a5
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| base_url = f"{client.api.base_url}/v{client.api._version}/_ping" | ||
| # Extract socket path from DEFAULT_UNIX_SOCKET (remove http+unix:// prefix) | ||
| socket_path = DEFAULT_UNIX_SOCKET.replace('http+unix://', '') | ||
|
|
||
| mock_obj.assert_called_once_with(base_url, | ||
| "/var/run/docker.sock", | ||
| socket_path, | ||
| 60, |
There was a problem hiding this comment.
The expected socket_path is derived by duplicating part of UnixHTTPAdapter's normalization logic (replace('http+unix://', '')). This same logic is repeated in multiple tests in this file and can drift from the real adapter behavior (e.g., leading-slash normalization). Consider factoring this into a small helper in the test module or deriving the expected value using the same normalization as docker.transport.unixconn.UnixHTTPAdapter to keep assertions consistent.
| base_url = f"{client.api.base_url}/v{client.api._version}/_ping" | ||
| # Extract socket path from DEFAULT_UNIX_SOCKET (remove http+unix:// prefix) | ||
| socket_path = DEFAULT_UNIX_SOCKET.replace('http+unix://', '') | ||
|
|
||
| mock_obj.assert_called_once_with(base_url, | ||
| "/var/run/docker.sock", | ||
| socket_path, | ||
| 60, |
There was a problem hiding this comment.
Same as earlier: socket_path = DEFAULT_UNIX_SOCKET.replace('http+unix://', '') duplicates adapter parsing logic and is repeated across tests. Consider using a shared helper to avoid divergence and repetition.
Problem
Docker Desktop for macOS v4.x+ changed the default socket location from /var/run/docker.sock to ~/.docker/run/docker.sock. The Python Docker SDK doesn't check this new location, causing ConnectionError / FileNotFoundError when users don't have DOCKER_HOST set.
Fixes #3271
Solution
This PR adds automatic socket discovery that checks multiple locations in order of preference:
/var/run/docker.sock (traditional Linux/macOS location)
~/.docker/run/docker.sock (Docker Desktop v4.x+ on macOS)
~/.docker/desktop/docker.sock (older Docker Desktop location)
Implementation Details
constants.py:
Added UNIX_SOCKET_PATHS list with known socket locations
Added _find_available_unix_socket() function that returns the first existing socket
DEFAULT_UNIX_SOCKET is now dynamically computed at import time
Falls back to /var/run/docker.sock if no socket exists (preserves existing error behavior)
Tests updated:
client_test.py - Uses dynamic DEFAULT_UNIX_SOCKET instead of hardcoded paths
utils_test.py - Updated parse_host tests to use dynamic socket path
Behavior
Backward compatible: Falls back to /var/run/docker.sock if no socket exists
DOCKER_HOST override: Still works - environment variable takes precedence
Docker contexts: Still take precedence over auto-detection
Windows unaffected: Only affects Unix socket discovery; Windows uses named pipes (npipe://)
Testing
Verified on macOS with Docker Desktop where:
/var/run/docker.sock does NOT exist
~/.docker/run/docker.sock exists
docker.from_env() now successfully connects without requiring DOCKER_HOST to be set.