Skip to content

Instantly share code, notes, and snippets.

@praul
Created January 25, 2025 07:56
Show Gist options
  • Save praul/05a9308b13a5025d90aa754bd7693c39 to your computer and use it in GitHub Desktop.
Save praul/05a9308b13a5025d90aa754bd7693c39 to your computer and use it in GitHub Desktop.
Mount Logs of docker containers in human-readable format or for mounting in to fail2ban-container
#!/bin/bash
LOGS_DIR="/docker/user/logs"
DOCKER_BASE_PATH="/docker/containers"
mkdir -p "$LOGS_DIR"
create_mount() {
local container_id=$1
local container_name=$2
# Volle Container-ID ermitteln
local full_container_id=$(docker inspect --format='{{.Id}}' "$container_id")
# Debug-Ausgabe
echo "Processing container: $container_name (Short ID: $container_id, Full ID: $full_container_id)"
# Zielverzeichnis und -datei
local target_dir="$LOGS_DIR/$container_name"
local target_file="$target_dir/${container_name}-json.log"
local source_file="$DOCKER_BASE_PATH/$full_container_id/${full_container_id}-json.log"
# Debug-Ausgabe
echo "Source file: $source_file"
echo "Target file: $target_file"
# Prüfe, ob die Log-Datei existiert
if [[ -f "$source_file" ]]; then
# Erstelle das Zielverzeichnis, falls es nicht existiert
mkdir -p "$target_dir"
# Debug-Ausgabe
echo "Log file exists. Ensuring mount..."
# Erstelle den Bind-Mount
if ! mountpoint -q "$target_file"; then
echo "Mounting log for container: $container_name (ID: $container_id)"
touch $target_file
mount --bind "$source_file" "$target_file"
else
echo "Log already mounted for container: $container_name"
fi
else
echo "Log file for container $container_name (ID: $container_id) does not exist, skipping."
fi
}
# Funktion zur Überprüfung und Aktualisierung der Mounts
update_mounts() {
# Sammle alle laufenden Container-IDs und -Namen
local containers=$(docker ps --format "{{.ID}} {{.Names}}")
# Debug-Ausgabe
echo "Active containers:"
echo "$containers"
# Iteriere über die Container und stelle sicher, dass die Logs gemountet sind
while IFS= read -r line; do
local container_id=$(echo "$line" | awk '{print $1}')
local container_name=$(echo "$line" | awk '{print $2}')
# Erstelle den Mount
create_mount "$container_id" "$container_name"
done <<< "$containers"
# Bereinige alte Mounts (für Container, die nicht mehr laufen)
for dir in "$LOGS_DIR"/*; do
if [[ -d $dir ]]; then
local existing_name=$(basename "$dir")
if ! echo "$containers" | grep -q " $existing_name$"; then
echo "Unmounting and cleaning up logs for container: $existing_name"
umount "$dir/${existing_name}-json.log" 2>/dev/null
rm -f "$dir/${existing_name}-json.log"
rmdir "$dir" 2>/dev/null # Entferne leere Verzeichnisse
fi
fi
done
}
# Haupt-Loop: Überwacht laufend Änderungen
main_loop() {
while true; do
echo "Running update_mounts at $(date)"
update_mounts
sleep 10 # Warte 10 Sekunden zwischen den Aktualisierungen
done
}
# Absturzschutz: Fange Signale ab und räume auf
trap "echo 'Stopping daemon and cleaning up...'; umount -R $LOGS_DIR; exit 0" SIGINT SIGTERM
# Starte die Hauptschleife
main_loop
@praul
Copy link
Author

praul commented Jan 25, 2025

I use this to mount logs from my docker containers into my fail2ban container.
Since docker normally stores logs with container-id (which will change on container restarts), this bash script running on the host continously mounts all logs to human-readable paths (i.e. container names). When using docker compose, your container names will always be the same, so you can now mount docker logs into other containers.

Set logging to json in source containers (and maybe choose a container name) (example docker-compose.yml)

services:
    vaultwarden:
        container_name: vaultwarden
        volumes:
            - './data/:/data/'
        ports:
            - '1234:80'
        image: 'vaultwarden/server:latest'
        logging:
            driver: json-file
            options:
               max-size: "10m" 
               max-file: "1"  
               

Adjust your paths in bash script and run it in background or as service.
Logs will now be at LOGS_DIR/container_name/container_name-json.log

In case of vaultwarden and with my path in bash script: /docker/user/logs/vaultwarden/vaultwarden-json.log

Mount docker-logs into target container (adjust path like /docker/user/logs here and in bash script)

services:
  fail2ban:
      image: crazymax/fail2ban:latest
      container_name: fail2ban
      restart: always
      volumes:
        - ./data:/data  
        - /docker/user/logs:/var/log/docker:ro         # Access to logs on host (read-only)
        - /var/log:/var/log/host:ro
      cap_add:
        - NET_ADMIN                        
        - NET_RAW
      network_mode: host
      env_file:
      - "./fail2ban.env"    

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment