build - prozess optimiert mit push nach zot

nginx-kill - > maint. site...
This commit is contained in:
br committed 2026-10-03 12:44:45 +02:00
1 parent 665135f87e
commit 64417d8353
19 files changed
+447 -61

No files matched your search

+62 -4
View File
@@ -1,6 +1,7 @@
// Package docker ist ein minimaler Client für die Docker Engine API über
// den Unix-Socket – genau das, was der Agent braucht: laufende Container
// mit Labels und Ports auflisten und Container-Events verfolgen. Bewusst
// den Unix-Socket – genau das, was der Agent braucht: Container mit Labels
// und Ports auflisten, Portzuordnungen gestoppter Container lesen und
// Container-Events verfolgen. Bewusst
// ohne Docker-SDK (schwere Abhängigkeit für zwei Endpunkte).
package docker
@@ -13,6 +14,9 @@ import (
"net"
"net/http"
"net/url"
"regexp"
"slices"
"strconv"
"strings"
)
@@ -85,9 +89,10 @@ func (c *Client) get(ctx context.Context, path string) (*http.Response, error) {
return resp, nil
}
// List liefert die laufenden Container.
// List liefert alle Container, auch gestoppte (State != "running"); bei
// diesen ist Ports leer, siehe PortBindings.
func (c *Client) List(ctx context.Context) ([]Container, error) {
resp, err := c.get(ctx, "/containers/json")
resp, err := c.get(ctx, "/containers/json?all=1")
if err != nil {
return nil, err
}
@@ -99,6 +104,59 @@ func (c *Client) List(ctx context.Context) ([]Container, error) {
return out, nil
}
var validID = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9_.-]*$`)
// PortBindings liefert die konfigurierten Portzuordnungen eines Containers
// (HostConfig.PortBindings) – auch wenn er gestoppt ist. Ohne festen
// Host-Port ist PublicPort 0. Sortiert nach "<port>/<proto>".
func (c *Client) PortBindings(ctx context.Context, id string) ([]Port, error) {
if !validID.MatchString(id) {
return nil, fmt.Errorf("docker: ungültige Container-ID %q", id)
}
resp, err := c.get(ctx, "/containers/"+id+"/json")
if err != nil {
return nil, err
}
defer resp.Body.Close()
var info struct {
HostConfig struct {
PortBindings map[string][]struct {
HostIP string `json:"HostIp"`
HostPort string `json:"HostPort"`
} `json:"PortBindings"`
} `json:"HostConfig"`
}
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
return nil, fmt.Errorf("docker: Container %s: %w", id, err)
}
keys := make([]string, 0, len(info.HostConfig.PortBindings))
for k := range info.HostConfig.PortBindings {
keys = append(keys, k)
}
slices.Sort(keys)
var out []Port
for _, k := range keys {
port, proto, _ := strings.Cut(k, "/")
private, err := strconv.ParseUint(port, 10, 16)
if err != nil {
continue
}
if proto == "" {
proto = "tcp"
}
bindings := info.HostConfig.PortBindings[k]
if len(bindings) == 0 {
out = append(out, Port{PrivatePort: uint16(private), Type: proto})
continue
}
for _, b := range bindings {
public, _ := strconv.ParseUint(b.HostPort, 10, 16) // "" → 0
out = append(out, Port{IP: b.HostIP, PrivatePort: uint16(private), PublicPort: uint16(public), Type: proto})
}
}
return out, nil
}
// Events verfolgt Container-Events, bis ctx endet oder der Stream abbricht.
// Der Event-Kanal wird danach geschlossen; errc liefert genau einen Wert
// (ctx.Err() bei Abbruch, sonst den Grund).