From 42dfb6b3d85a3d9f7bcfc7d6023e58e148778877 Mon Sep 17 00:00:00 2001 From: Nemental <15136847+Nemental@users.noreply.github.com> Date: Wed, 30 Jul 2025 09:31:41 +0200 Subject: [PATCH 1/4] feat: add type and function for docker endpoint parsing --- docker/client.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docker/client.go b/docker/client.go index 226e099..4258b15 100644 --- a/docker/client.go +++ b/docker/client.go @@ -53,6 +53,32 @@ type Network struct { DNSNames []string `json:"dnsNames,omitempty"` } +// Strcuture parts of docker api endpoint +type dockerHost struct { + protocol string // e.g. unix, http, tcp, ssh + address string // e.g. "/var/run/docker.sock" or "host:port" +} + +// Parse the docker api endpoint into its parts +func parseDockerHost(raw string) (dockerHost, error) { + switch { + case strings.HasPrefix(raw, "unix://"): + return dockerHost{"unix", strings.TrimPrefix(raw, "unix://")}, nil + case strings.HasPrefix(raw, "ssh://"): + // SSH is treated as TCP-like transport by the docker client + return dockerHost{"ssh", strings.TrimPrefix(raw, "ssh://")}, nil + case strings.HasPrefix(raw, "tcp://"), strings.HasPrefix(raw, "http://"), strings.HasPrefix(raw, "https://"): + s := raw + s = strings.TrimPrefix(s, "tcp://") + s = strings.TrimPrefix(s, "http://") + s = strings.TrimPrefix(s, "https://") + return dockerHost{"tcp", s}, nil + default: + // default fallback to unix + return dockerHost{"unix", raw}, nil + } +} + // CheckSocket checks if Docker socket is available func CheckSocket(socketPath string) bool { // Use the provided socket path or default to standard location From a79dccc0e497d3ac0cb56dc17f74b12599fb9419 Mon Sep 17 00:00:00 2001 From: Nemental <15136847+Nemental@users.noreply.github.com> Date: Wed, 30 Jul 2025 09:36:19 +0200 Subject: [PATCH 2/4] feat: checksocket protocol support --- docker/client.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/docker/client.go b/docker/client.go index 4258b15..fbda059 100644 --- a/docker/client.go +++ b/docker/client.go @@ -83,18 +83,25 @@ func parseDockerHost(raw string) (dockerHost, error) { func CheckSocket(socketPath string) bool { // Use the provided socket path or default to standard location if socketPath == "" { - socketPath = "/var/run/docker.sock" + socketPath = "unix:///var/run/docker.sock" + } + host, err := parseDockerHost(socketPath) + if err != nil { + logger.Debug("Invalid Docker socket path '%s': %v", socketPath, err) + return false } + protocol := host.protocol + addr := host.address - // Try to create a connection to the Docker socket - conn, err := net.Dial("unix", socketPath) + // ssh might need different verification, but tcp works for basic reachability + conn, err := net.DialTimeout(protocol, addr, 2*time.Second) if err != nil { - logger.Debug("Docker socket not available at %s: %v", socketPath, err) + logger.Debug("Docker not reachable via %s at %s: %v", protocol, addr, err) return false } defer conn.Close() - logger.Debug("Docker socket is available at %s", socketPath) + logger.Debug("Docker reachable via %s at %s", protocol, addr) return true } From e9dbfb239b045671a76f864ac9cf328ec294751b Mon Sep 17 00:00:00 2001 From: Nemental <15136847+Nemental@users.noreply.github.com> Date: Wed, 30 Jul 2025 09:36:53 +0200 Subject: [PATCH 3/4] fix: remove hardcoded protocol from socket path --- docker/client.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docker/client.go b/docker/client.go index fbda059..f8b9d0c 100644 --- a/docker/client.go +++ b/docker/client.go @@ -165,7 +165,7 @@ func ListContainers(socketPath string, enforceNetworkValidation bool) ([]Contain // Create client with custom socket path cli, err := client.NewClientWithOpts( - client.WithHost("unix://"+socketPath), + client.WithHost(socketPath), client.WithAPIVersionNegotiation(), ) if err != nil { @@ -215,7 +215,6 @@ func ListContainers(socketPath string, enforceNetworkValidation bool) ([]Contain hostname = containerInfo.Config.Hostname } - // Skip host container if set if hostContainerId != "" && c.ID == hostContainerId { continue From a9d8ec0b1e36bfb1da0e13000fe656590774bd07 Mon Sep 17 00:00:00 2001 From: Nemental <15136847+Nemental@users.noreply.github.com> Date: Wed, 30 Jul 2025 15:28:55 +0200 Subject: [PATCH 4/4] docs: update docker socket part --- README.md | 25 +++++++++++++++++++++++-- main.go | 2 +- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 69a4fa8..8e03c2a 100644 --- a/README.md +++ b/README.md @@ -205,7 +205,27 @@ Newt can integrate with the Docker socket to provide remote inspection of Docker **Configuration:** -You can specify the Docker socket path using the `--docker-socket` CLI argument or by setting the `DOCKER_SOCKET` environment variable. On most linux systems the socket is `/var/run/docker.sock`. When deploying newt as a container, you need to mount the host socket as a volume for the newt container to access it. If the Docker socket is not available or accessible, Newt will gracefully disable Docker integration and continue normal operation. +You can specify the Docker socket path using the `--docker-socket` CLI argument or by setting the `DOCKER_SOCKET` environment variable. If the Docker socket is not available or accessible, Newt will gracefully disable Docker integration and continue normal operation. + +Supported values include: + +- Local UNIX socket (default): + >You must mount the socket file into the container using a volume, so Newt can access it. + + `unix:///var/run/docker.sock` + +- TCP socket (e.g., via Docker Socket Proxy): + + `tcp://localhost:2375` + +- HTTP/HTTPS endpoints (e.g., remote Docker APIs): + + `http://your-host:2375` + +- SSH connections (experimental, requires SSH setup): + + `ssh://user@host` + ```yaml services: @@ -219,8 +239,9 @@ services: - PANGOLIN_ENDPOINT=https://example.com - NEWT_ID=2ix2t8xk22ubpfy - NEWT_SECRET=nnisrfsdfc7prqsp9ewo1dvtvci50j5uiqotez00dgap0ii2 - - DOCKER_SOCKET=/var/run/docker.sock + - DOCKER_SOCKET=unix:///var/run/docker.sock ``` +>If you previously used just a path like `/var/run/docker.sock`, it still works — Newt assumes it is a UNIX socket by default. #### Hostnames vs IPs diff --git a/main.go b/main.go index dbb141f..14c74d3 100644 --- a/main.go +++ b/main.go @@ -158,7 +158,7 @@ func main() { flag.StringVar(&tlsPrivateKey, "tls-client-cert", "", "Path to client certificate used for mTLS") } if dockerSocket == "" { - flag.StringVar(&dockerSocket, "docker-socket", "", "Path to Docker socket (typically /var/run/docker.sock)") + flag.StringVar(&dockerSocket, "docker-socket", "", "Path or address to Docker socket (typically unix:///var/run/docker.sock)") } if pingIntervalStr == "" { flag.StringVar(&pingIntervalStr, "ping-interval", "3s", "Interval for pinging the server (default 3s)")