diff --git a/internal/sys/docker.go b/internal/sys/docker.go index dcfc7d8a8..241d4dd6d 100644 --- a/internal/sys/docker.go +++ b/internal/sys/docker.go @@ -102,6 +102,21 @@ func runDockerInspect(containerID, formatTemplate string) (string, error) { return result, nil } +// IsHostNetworkMode uses docker inspect to determine whether the container was +// started with `--network host`. Host-networked containers do not have published +// port mappings in NetworkSettings.Ports (Docker discards them), so port-mapping +// checks must be skipped for them. +func IsHostNetworkMode(containerID string) (bool, error) { + output, err := runDockerInspect(containerID, "{{.HostConfig.NetworkMode}}") + if err != nil { + return false, err + } + + hostNetwork := output == "host" + logDocker.Printf("Network mode check: containerID=%s, networkMode=%s, host=%v", containerID, output, hostNetwork) + return hostNetwork, nil +} + // CheckPortMapping uses docker inspect to verify that the specified port is mapped. func CheckPortMapping(containerID, port string) (bool, error) { logDocker.Printf("Checking port mapping: containerID=%s, port=%s", containerID, port) diff --git a/internal/sys/docker_test.go b/internal/sys/docker_test.go index 969bc746a..04339042e 100644 --- a/internal/sys/docker_test.go +++ b/internal/sys/docker_test.go @@ -291,6 +291,49 @@ func TestCheckPortMapping(t *testing.T) { } } +func TestIsHostNetworkMode(t *testing.T) { + tests := []struct { + name string + containerID string + port string + shouldError bool + dockerHost string // if set, DOCKER_HOST is overridden for this subtest + }{ + { + name: "empty container ID", + containerID: "", + shouldError: true, + }, + { + name: "invalid container ID", + containerID: "invalid;id", + shouldError: true, + }, + { + name: "valid container ID format - container absent", + containerID: "abc123def4567890", + shouldError: true, // docker inspect will fail: socket doesn't exist + dockerHost: "unix:///nonexistent/docker.sock", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.dockerHost != "" { + t.Setenv("DOCKER_HOST", tt.dockerHost) + } + hostNetwork, err := IsHostNetworkMode(tt.containerID) + + if tt.shouldError { + require.Error(t, err, "Expected error for %s", tt.name) + assert.False(t, hostNetwork, "Should not be reported as host network on error") + } else { + require.NoError(t, err, "Unexpected error") + } + }) + } +} + func TestCheckStdinInteractive(t *testing.T) { tests := []struct { name string