Files
dockernet-inspector/dockernet-inspector.v1.sh

455 lines
14 KiB
Bash

#!/usr/bin/env bash
# Script Name: dockernet-inspector.v1.sh
# Beschreibung: Dockernet Inspector - Verwaltet und inspiziert Docker-Netzwerke
# - Alle Netzwerke auflisten
# - Details zu einem spezifischen Docker-Netzwerk anzeigen
# - Belegte IPs je Netzwerk und netzwerkuebergreifend ausgeben
# - Ungenutzte Netzwerke (ohne Container) anzeigen
# - Netzwerke interaktiv auswaehlen und loeschen
# Verwendung: bash ./dockernet-inspector.v1.sh [BEFEHL] [OPTIONS]
# Befehle:
# networks - Alle Docker Netzwerke auflisten
# inspect - Details zu einem Netzwerk anzeigen (Standard)
# ips - Belegte IPs in einem Netzwerk
# ips-all - Belegte IPs in allen Netzwerken
# unused-networks - Netzwerke ohne verbundene Container
# delete-networks - Netzwerke interaktiv auswaehlen und loeschen
# help, -h, --help - Diese Hilfe anzeigen
# Autor: Patrick Asmus
# Web: https://www.cleveradmin.de
# Git-Reposit.: https://git.techniverse.net/scriptos/dockernet-inspector.git
# Version: 1.6.0
# Datum: 10.04.2026
# Modifikation: Schutz fuer Docker-Standardnetzwerke (bridge, host, none) hinzugefuegt;
# Detailansicht zeigt Hinweis statt Bridge-Daten, Loeschen wird blockiert
#####################################################
set -uo pipefail
TABLE_LINE_WIDTH=80
INTERACTIVE_MODE=false
print_rule() {
local char="$1"
printf '%*s\n' "$TABLE_LINE_WIDTH" '' | tr ' ' "$char"
}
print_table_title() {
local title="$1"
echo "$title"
print_rule "="
}
# Hilfe-Funktion
show_help() {
cat <<HELP
Dockernet Inspector v1.6.0 - Docker Netzwerk Verwaltungstool
VERWENDUNG:
$0 - Interaktiver Modus (Menü)
$0 networks - Alle Docker Netzwerke auflisten
$0 inspect <netzwerk> - Details zu einem Netzwerk anzeigen
$0 ips <netzwerk> - Belegte IPs in einem Netzwerk anzeigen
$0 ips-all - Belegte IPs in allen Netzwerken anzeigen
$0 unused-networks - Ungenutzte Netzwerke (ohne Container) anzeigen
$0 delete-networks - Netzwerke interaktiv auswaehlen und loeschen
$0 <netzwerk> - Alias fuer 'inspect <netzwerk>'
$0 help - Diese Hilfe anzeigen
BEFEHLE:
networks Listet alle verfuegbaren Docker Netzwerke auf
ips <netzwerk> Zeigt Containername und IPv4-Adresse im angegebenen Netzwerk
ips-all Zeigt alle belegten IPv4-Adressen in allen Netzwerken (aufsteigend)
unused-networks Zeigt alle Docker Netzwerke ohne verbundene Container
delete-networks Netzwerk per Nummer auswaehlen und loeschen;
Docker-Standardnetzwerke (bridge, host, none) sind geschuetzt
inspect <netzwerk> Zeigt detaillierte Informationen zu einem Netzwerk:
- Netzwerktyp (Driver)
- Bridge-Interface
- Subnetz und Gateway
- Interface-Status
- Netzwerk-Statistiken (RX/TX bytes und packets)
help Zeigt diese Hilfe an
BEISPIELE:
$0 networks
$0 ips mynetwork
$0 ips-all
$0 unused-networks
$0 delete-networks
$0 inspect mynetwork
$0 mynetwork
$0 -h
HELP
}
# Funktion zum Auflisten aller Docker Netzwerke
list_networks() {
local table_output header
print_table_title "Verfuegbare Docker Netzwerke:"
table_output="$(docker network ls --format "table {{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.Scope}}")" || {
echo "Fehler: Docker Netzwerke konnten nicht abgerufen werden."
exit 2
}
header="$(printf "%s\n" "$table_output" | head -n 1)"
printf "%s\n" "$header"
print_rule "-"
printf "%s\n" "$table_output" | tail -n +2
}
print_dynamic_table() {
local data="$1"
local formatted
local header
if command -v column >/dev/null 2>&1; then
formatted="$(printf "%b" "$data" | column -t -s $'\t')"
else
formatted="$(printf "%b" "$data")"
fi
header="$(printf "%s\n" "$formatted" | head -n 1)"
printf "%s\n" "$header"
print_rule "-"
printf "%s\n" "$formatted" | tail -n +2
}
list_ips_in_network() {
local net="$1"
local rows table_data
rows="$(docker network inspect "$net" --format '{{range $id, $c := .Containers}}{{println $c.Name $c.IPv4Address}}{{end}}' 2>/dev/null || true)"
[[ -z "$rows" ]] && {
echo "Keine Container mit IPv4-Adresse im Netzwerk '$net' gefunden."
exit 0
}
print_table_title "Belegte IP-Adressen im Netzwerk '$net':"
table_data=$'CONTAINER\tIP\n'
while read -r cname ipcidr; do
[[ -z "${cname:-}" || -z "${ipcidr:-}" ]] && continue
table_data+="${cname}"$'\t'"${ipcidr%%/*}"$'\n'
done < <(printf "%s\n" "$rows" | sort -k2,2V)
print_dynamic_table "$table_data"
}
list_ips_all_networks() {
local nets rows table_data
rows=""
nets="$(docker network ls --format '{{.Name}}' 2>/dev/null || true)"
[[ -z "$nets" ]] && {
echo "Fehler: Docker Netzwerke konnten nicht abgerufen werden."
exit 2
}
while read -r net; do
[[ -z "${net:-}" ]] && continue
while read -r cname ipcidr; do
[[ -z "${cname:-}" || -z "${ipcidr:-}" ]] && continue
rows+="${net}"$'\t'"${cname}"$'\t'"${ipcidr%%/*}"$'\n'
done < <(docker network inspect "$net" --format '{{range $id, $c := .Containers}}{{println $c.Name $c.IPv4Address}}{{end}}' 2>/dev/null || true)
done < <(printf "%s\n" "$nets")
[[ -z "$rows" ]] && {
echo "Keine belegten IPv4-Adressen in Docker Netzwerken gefunden."
exit 0
}
print_table_title "Belegte IP-Adressen in allen Netzwerken (aufsteigend):"
table_data=$'NETZWERK\tCONTAINER\tIP\n'
while IFS=$'\t' read -r net cname ip; do
[[ -z "${net:-}" || -z "${cname:-}" || -z "${ip:-}" ]] && continue
table_data+="${net}"$'\t'"${cname}"$'\t'"${ip}"$'\n'
done < <(printf "%s" "$rows" | sort -t $'\t' -k3,3V -k1,1 -k2,2)
print_dynamic_table "$table_data"
}
list_unused_networks() {
local nets net containers table_data has_unused
nets="$(docker network ls --format '{{.Name}}' 2>/dev/null || true)"
[[ -z "$nets" ]] && {
echo "Fehler: Docker Netzwerke konnten nicht abgerufen werden."
exit 2
}
table_data=$'NAME\tDRIVER\tSCOPE\n'
has_unused=false
while read -r net; do
[[ -z "${net:-}" ]] && continue
containers="$(docker network inspect "$net" --format '{{len .Containers}}' 2>/dev/null || true)"
if [[ "${containers:-0}" -eq 0 ]]; then
local driver scope
driver="$(docker network inspect "$net" --format '{{.Driver}}' 2>/dev/null || true)"
scope="$(docker network inspect "$net" --format '{{.Scope}}' 2>/dev/null || true)"
table_data+="${net}"$'\t'"${driver}"$'\t'"${scope}"$'\n'
has_unused=true
fi
done < <(printf "%s\n" "$nets")
if ! $has_unused; then
echo "Alle Docker Netzwerke haben mindestens einen verbundenen Container."
return 0
fi
print_table_title "Ungenutzte Docker Netzwerke (keine Container verbunden):"
print_dynamic_table "$table_data"
}
delete_networks() {
local nets
nets="$(docker network ls --format '{{.Name}}' 2>/dev/null || true)"
if [[ -z "$nets" ]]; then
echo "Fehler: Keine Docker Netzwerke gefunden."
return 1
fi
local -a net_array
mapfile -t net_array <<< "$nets"
echo ""
echo "Verfuegbare Docker Netzwerke:"
echo ""
local i
for ((i=0; i<${#net_array[@]}; i++)); do
local suffix=""
[[ "${net_array[$i]}" == "bridge" || "${net_array[$i]}" == "host" || "${net_array[$i]}" == "none" ]] && suffix=" (Standard - nicht loeschbar)"
printf " %d. %s%s\n" "$((i+1))" "${net_array[$i]}" "$suffix"
done
echo ""
read -rp "Nummer des Netzwerks eingeben (0 = Abbrechen): " choice
if [[ "$choice" == "0" || -z "$choice" ]]; then
echo "Abgebrochen."
return 0
fi
if ! [[ "$choice" =~ ^[0-9]+$ ]] || ((choice < 1 || choice > ${#net_array[@]})); then
echo "Fehler: Ungueltige Nummer."
return 1
fi
local selected_net="${net_array[$((choice-1))]}"
if [[ "$selected_net" == "bridge" || "$selected_net" == "host" || "$selected_net" == "none" ]]; then
echo "FEHLER: '$selected_net' ist ein Docker-Standardnetzwerk und kann nicht geloescht werden."
return 1
fi
echo ""
read -rp "Netzwerk '$selected_net' wirklich loeschen? [j/N]: " confirm
if [[ "$confirm" != "j" && "$confirm" != "J" ]]; then
echo "Abgebrochen."
return 0
fi
echo ""
if docker network rm "$selected_net" 2>/dev/null; then
echo "OK: Netzwerk '$selected_net' erfolgreich geloescht."
else
echo "FEHLER: Netzwerk '$selected_net' konnte nicht geloescht werden (wird moeglicherweise noch genutzt)."
fi
}
# Interaktive Menü-Funktion
interactive_menu() {
while true; do
echo ""
print_rule "="
echo "Dockernet Inspector - Interaktives Menü"
print_rule "="
echo ""
echo "1. Alle Netzwerke auflisten"
echo "2. Detaillierte Infos zu einem Netzwerk"
echo "3. IPs eines Netzwerks anzeigen"
echo "4. Alle belegten IPs anzeigen"
echo "5. Ungenutzte Netzwerke anzeigen"
echo "6. Netzwerke loeschen"
echo "0. Beenden"
echo ""
read -rp "Bitte waehlen Sie eine Option (0-6): " choice
echo ""
case "$choice" in
1)
list_networks
;;
2)
if select_and_inspect_network; then
:
fi
;;
3)
nets="$(docker network ls --format '{{.Name}}' 2>/dev/null || true)"
if [[ -z "$nets" ]]; then
echo "Fehler: Keine Docker Netzwerke gefunden."
continue
fi
echo "Verfuegbare Netzwerke:"
select net in $nets; do
if [[ -n "$net" ]]; then
list_ips_in_network "$net"
break
else
echo "Ungueltige Auswahl. Bitte versuchen Sie es erneut."
fi
done
;;
4)
list_ips_all_networks
;;
5)
list_unused_networks
;;
6)
delete_networks
;;
0)
echo "Auf Wiedersehen!"
exit 0
;;
*)
echo "FEHLER: Ungueltige Eingabe '$choice'. Bitte geben Sie eine Nummer zwischen 0 und 6 ein."
sleep 1
;;
esac
done
}
# Funktion zur Auswahl und Inspektion eines Netzwerks
select_and_inspect_network() {
local nets net
nets="$(docker network ls --format '{{.Name}}' 2>/dev/null || true)"
if [[ -z "$nets" ]]; then
echo "Fehler: Keine Docker Netzwerke gefunden."
return 1
fi
echo "Verfuegbare Netzwerke:"
select net in $nets; do
if [[ -n "$net" ]]; then
NET="$net"
inspect_network "$NET"
return 0
else
echo "Ungueltige Auswahl. Bitte versuchen Sie es erneut."
fi
done
}
# Separate Funktion fuer Netzwerk-Inspektion
inspect_network() {
local NET="$1"
local DRIVER
DRIVER="$(docker network inspect "$NET" --format '{{.Driver}}' 2>/dev/null || true)"
[[ -z "$DRIVER" ]] && { echo "Fehler: Netzwerk '$NET' nicht gefunden."; return 2; }
echo ""
print_rule "="
echo "Detaillerte Informationen fuer Netzwerk: $NET"
print_rule "="
echo ""
# Sonderbehandlung fuer Docker-Standardnetzwerke
if [[ "$NET" == "none" || "$NET" == "host" || "$NET" == "bridge" ]]; then
cat <<OUT
Docker-Netzwerk : $NET
Driver : $DRIVER
Hinweis : Dies ist ein Docker-Standardnetzwerk und kann nicht geloescht werden.
OUT
echo ""
return 0
fi
# 1) Netzwerk-ID und Bridge-Name
local ID BR_RAW IF SUBNET GATEWAY state rxb txb rxp txp
ID="$(docker network inspect "$NET" --format '{{.Id}}' 2>/dev/null || true)"
BR_RAW="$(docker network inspect "$NET" --format '{{index .Options "com.docker.network.bridge.name"}}' 2>/dev/null || true)"
if [[ -z "$BR_RAW" || "$BR_RAW" == "<no value>" ]]; then
IF="br-${ID:0:12}"
else
IF="$BR_RAW"
fi
# 2) Subnet/Gateway
SUBNET="$(docker network inspect "$NET" --format '{{(index .IPAM.Config 0).Subnet}}' 2>/dev/null || true)"
GATEWAY="$(docker network inspect "$NET" --format '{{(index .IPAM.Config 0).Gateway}}' 2>/dev/null || true)"
# 3) Interface-Status & Stats
state="unknown"; rxb=0; txb=0; rxp=0; txp=0
if ip link show "$IF" &>/dev/null; then
state="$(cat /sys/class/net/"$IF"/operstate 2>/dev/null || echo unknown)"
rxb="$(cat /sys/class/net/"$IF"/statistics/rx_bytes 2>/dev/null || echo 0)"
txb="$(cat /sys/class/net/"$IF"/statistics/tx_bytes 2>/dev/null || echo 0)"
rxp="$(cat /sys/class/net/"$IF"/statistics/rx_packets 2>/dev/null || echo 0)"
txp="$(cat /sys/class/net/"$IF"/statistics/tx_packets 2>/dev/null || echo 0)"
fi
cat <<OUT
Docker-Netzwerk : $NET
Driver : $DRIVER
Bridge-Interface : $IF
Subnet/Gateway : ${SUBNET:--} / ${GATEWAY:--}
OperState : $state
RX bytes/packets : $rxb / $rxp
TX bytes/packets : $txb / $txp
OUT
echo ""
}
# Argument-Verarbeitung
COMMAND="${1:-}"
case "$COMMAND" in
networks)
list_networks
exit 0
;;
ips)
NET="${2:-}"
[[ -z "$NET" ]] && { echo "Fehler: Netzwerkname erforderlich. Verwendung: $0 ips <docker-network-name>"; exit 1; }
list_ips_in_network "$NET"
exit 0
;;
ips-all)
list_ips_all_networks
exit 0
;;
unused-networks)
list_unused_networks
exit 0
;;
delete-networks)
delete_networks
exit 0
;;
help | -h | --help)
show_help
exit 0
;;
inspect)
NET="${2:-}"
[[ -z "$NET" ]] && { echo "Fehler: Netzwerkname erforderlich. Verwendung: $0 inspect <docker-network-name>"; exit 1; }
inspect_network "$NET"
exit 0
;;
"")
# Starte interaktiven Modus, wenn keine Argumente uebergeben wurden
interactive_menu
exit 0
;;
*)
# Kompatibilitaet: Wenn erstes Argument kein bekannter Befehl ist, behandle es als Netzwerkname
NET="$COMMAND"
inspect_network "$NET"
exit 0
;;
esac