mirror of
https://github.com/fosrl/newt.git
synced 2026-02-27 23:36:41 +00:00
Merge pull request #97 from Nemental/feat/docker-socket-protocol
feat: docker socket protocol
This commit is contained in:
25
README.md
25
README.md
@@ -229,7 +229,27 @@ Newt can integrate with the Docker socket to provide remote inspection of Docker
|
|||||||
|
|
||||||
**Configuration:**
|
**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
|
```yaml
|
||||||
services:
|
services:
|
||||||
@@ -243,8 +263,9 @@ services:
|
|||||||
- PANGOLIN_ENDPOINT=https://example.com
|
- PANGOLIN_ENDPOINT=https://example.com
|
||||||
- NEWT_ID=2ix2t8xk22ubpfy
|
- NEWT_ID=2ix2t8xk22ubpfy
|
||||||
- NEWT_SECRET=nnisrfsdfc7prqsp9ewo1dvtvci50j5uiqotez00dgap0ii2
|
- 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
|
#### Hostnames vs IPs
|
||||||
|
|
||||||
|
|||||||
@@ -53,22 +53,55 @@ type Network struct {
|
|||||||
DNSNames []string `json:"dnsNames,omitempty"`
|
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
|
// CheckSocket checks if Docker socket is available
|
||||||
func CheckSocket(socketPath string) bool {
|
func CheckSocket(socketPath string) bool {
|
||||||
// Use the provided socket path or default to standard location
|
// Use the provided socket path or default to standard location
|
||||||
if socketPath == "" {
|
if socketPath == "" {
|
||||||
socketPath = "/var/run/docker.sock"
|
socketPath = "unix:///var/run/docker.sock"
|
||||||
}
|
}
|
||||||
|
host, err := parseDockerHost(socketPath)
|
||||||
// Try to create a connection to the Docker socket
|
|
||||||
conn, err := net.Dial("unix", socketPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Debug("Docker socket not available at %s: %v", socketPath, err)
|
logger.Debug("Invalid Docker socket path '%s': %v", socketPath, err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
protocol := host.protocol
|
||||||
|
addr := host.address
|
||||||
|
|
||||||
|
// 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 not reachable via %s at %s: %v", protocol, addr, err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
logger.Debug("Docker socket is available at %s", socketPath)
|
logger.Debug("Docker reachable via %s at %s", protocol, addr)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +165,7 @@ func ListContainers(socketPath string, enforceNetworkValidation bool) ([]Contain
|
|||||||
|
|
||||||
// Create client with custom socket path
|
// Create client with custom socket path
|
||||||
cli, err := client.NewClientWithOpts(
|
cli, err := client.NewClientWithOpts(
|
||||||
client.WithHost("unix://"+socketPath),
|
client.WithHost(socketPath),
|
||||||
client.WithAPIVersionNegotiation(),
|
client.WithAPIVersionNegotiation(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -182,7 +215,6 @@ func ListContainers(socketPath string, enforceNetworkValidation bool) ([]Contain
|
|||||||
hostname = containerInfo.Config.Hostname
|
hostname = containerInfo.Config.Hostname
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Skip host container if set
|
// Skip host container if set
|
||||||
if hostContainerId != "" && c.ID == hostContainerId {
|
if hostContainerId != "" && c.ID == hostContainerId {
|
||||||
continue
|
continue
|
||||||
|
|||||||
2
main.go
2
main.go
@@ -173,7 +173,7 @@ func main() {
|
|||||||
flag.StringVar(&tlsPrivateKey, "tls-client-cert", "", "Path to client certificate used for mTLS")
|
flag.StringVar(&tlsPrivateKey, "tls-client-cert", "", "Path to client certificate used for mTLS")
|
||||||
}
|
}
|
||||||
if dockerSocket == "" {
|
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 == "" {
|
if pingIntervalStr == "" {
|
||||||
flag.StringVar(&pingIntervalStr, "ping-interval", "3s", "Interval for pinging the server (default 3s)")
|
flag.StringVar(&pingIntervalStr, "ping-interval", "3s", "Interval for pinging the server (default 3s)")
|
||||||
|
|||||||
Reference in New Issue
Block a user