Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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

Expand Down
46 changes: 39 additions & 7 deletions docker/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,55 @@ 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
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
}

Expand Down Expand Up @@ -132,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 {
Expand Down Expand Up @@ -182,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
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)")
Expand Down