@@ -135,6 +135,68 @@ def test_get_docker_host(m_subprocess):
135135 assert host == endpoint ["result" ]
136136
137137
138+ @patch ("sagemaker.local.utils.subprocess" )
139+ def test_get_docker_host_rootless_docker (m_subprocess ):
140+ """Test that rootless Docker is detected and returns fixed IP"""
141+ # Mock docker info process for rootless Docker
142+ info_process_mock = Mock ()
143+ info_attrs = {"communicate.return_value" : (b"Cgroup Driver: none" , b"" ), "returncode" : 0 }
144+ info_process_mock .configure_mock (** info_attrs )
145+ m_subprocess .Popen .return_value = info_process_mock
146+
147+ host = sagemaker .local .utils .get_docker_host ()
148+ assert host == "172.17.0.1"
149+
150+ # Verify docker info was called
151+ m_subprocess .Popen .assert_called_with (
152+ ["docker" , "info" ], stdout = m_subprocess .PIPE , stderr = m_subprocess .PIPE
153+ )
154+
155+
156+ @patch ("sagemaker.local.utils.subprocess" )
157+ def test_get_docker_host_traditional_docker (m_subprocess ):
158+ """Test that traditional Docker falls back to existing logic"""
159+ scenarios = [
160+ {
161+ "docker_info" : b"Cgroup Driver: cgroupfs" ,
162+ "context_host" : "tcp://host:port" ,
163+ "result" : "host" ,
164+ },
165+ {
166+ "docker_info" : b"Cgroup Driver: cgroupfs" ,
167+ "context_host" : "unix:///var/run/docker.sock" ,
168+ "result" : "localhost" ,
169+ },
170+ {
171+ "docker_info" : b"Cgroup Driver: cgroupfs" ,
172+ "context_host" : "fd://something" ,
173+ "result" : "localhost" ,
174+ },
175+ ]
176+
177+ for scenario in scenarios :
178+ # Mock docker info process for traditional Docker
179+ info_process_mock = Mock ()
180+ info_attrs = {"communicate.return_value" : (scenario ["docker_info" ], b"" ), "returncode" : 0 }
181+ info_process_mock .configure_mock (** info_attrs )
182+
183+ # Mock docker context inspect process
184+ context_return_value = (
185+ '[\n {\n "Endpoints":{\n "docker":{\n "Host": "%s"}\n }\n }\n ]\n ' % scenario ["context_host" ]
186+ )
187+ context_process_mock = Mock ()
188+ context_attrs = {
189+ "communicate.return_value" : (context_return_value .encode ("utf-8" ), None ),
190+ "returncode" : 0 ,
191+ }
192+ context_process_mock .configure_mock (** context_attrs )
193+
194+ m_subprocess .Popen .side_effect = [info_process_mock , context_process_mock ]
195+
196+ host = sagemaker .local .utils .get_docker_host ()
197+ assert host == scenario ["result" ]
198+
199+
138200@pytest .mark .parametrize (
139201 "json_path, expected" ,
140202 [
0 commit comments