init: clean history with no PII

Toto repo ma novou cistou historii (1 commit). Predchozi historie
byla smazana, protoze obsahovala osobni udaje (IP, emaily, hesla,
klice, tokeny, Volume cesty). Soubory v aktualnim commit uz tyto
udaje neobsahuji (nahradeno placeholdery <server-ip>, CHANGE_ME,
admin@example.com atd.).

Pokud chces zpet kompletni seznam starych commitu, mas je ve svem
lokalnim working tree - git log --all ukaze prazdno (protoze jsme
smazali .git/ a zacali znovu).
This commit is contained in:
2026-08-01 19:51:59 +02:00
commit 682f522cb9
10 changed files with 1560 additions and 0 deletions
+181
View File
@@ -0,0 +1,181 @@
#!/usr/bin/env bash
#
# docker-update.sh — bezpečná aktualizace Docker Compose projektů
#
# - zastaví všechny kontejnery,
# - stáhne nové image (docker compose pull),
# - ověří, že se image skutečně změnil (jinak přeskočí),
# - spustí kontejnery z nových image,
# - zkontroluje health checks,
# - ponechá staré image pro případný rollback (docker image prune -f na konci,
# ale jen dangling, ne všechno).
#
# Použití:
# ./docker-update.sh # aktualizuje všechny projekty v <docker-projects-root>
# ./docker-update.sh nginx mattermost # aktualizuje vybrané projekty
# ./docker-update.sh --help # nápověda
#
set -euo pipefail
usage() {
sed -n '2,15p' "$0" | sed 's/^# \{0,1\}//'
}
for arg in "$@"; do
case "$arg" in
--help|-h) usage; exit 0 ;;
esac
done
DOCKERY="${DOCKERY:-<docker-projects-root>}"
LOG="${LOG:-/tmp/docker-update-$(date +%Y-%m-%d_%H-%M).log}"
PRUNE_DANGLING="${PRUNE_DANGLING:-1}" # 1 = docker image prune -f (dangling only)
HEALTH_TIMEOUT="${HEALTH_TIMEOUT:-60}" # sekund na health check po startu
# Barevné výstupy (pokud terminál umí)
if [ -t 1 ]; then
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
else
RED=''; GREEN=''; YELLOW=''; NC=''
fi
log() { printf '%s[%s]%s %s\n' "$GREEN" "$(date '+%H:%M:%S')" "$NC" "$*" | tee -a "$LOG"; }
warn() { printf '%s[%s]%s %s\n' "$YELLOW" "$(date '+%H:%M:%S')" "$NC" "$*" | tee -a "$LOG"; }
err() { printf '%s[%s]%s %s\n' "$RED" "$(date '+%H:%M:%S')" "$NC" "$*" | tee -a "$LOG"; }
# Kontrola, že docker běží
if ! docker info >/dev/null 2>&1; then
err "Docker není dostupný. Spusť Docker Desktop a zkus znovu."
exit 1
fi
# Najdi projekty
if [ "$#" -gt 0 ]; then
PROJECTS=("$@")
else
PROJECTS=()
for d in "$DOCKERY"/*/; do
[ -d "$d" ] || continue
if compgen -G "$d/docker-compose.y*ml" > /dev/null; then
PROJECTS+=("$(basename "$d")")
fi
done
fi
if [ "${#PROJECTS[@]}" -eq 0 ]; then
err "Nebyly nalezeny žádné Docker Compose projekty v $DOCKERY"
exit 1
fi
log "Nalezeno ${#PROJECTS[@]} projektů: ${PROJECTS[*]}"
# Pre-flight: ulož si, co běží
log "=== PRE-FLIGHT ==="
BEFORE_RUNNING=$(docker ps --format '{{.Names}}')
log "Běžící kontejnery před aktualizací:"
printf ' %s\n' $BEFORE_RUNNING
UPDATED=()
SKIPPED=()
FAILED=()
for project in "${PROJECTS[@]}"; do
cd "$DOCKERY/$project"
if ! compgen -G "docker-compose.y*ml" > /dev/null; then
warn "[$project] nemá docker-compose soubor, přeskakuji"
SKIPPED+=("$project")
continue
fi
log ""
log "=== [$project] ==="
# Zaznamenej aktuální image ID
BEFORE_DIGESTS=$(docker compose ps -q 2>/dev/null \
| xargs -I{} docker inspect --format='{{.Image}}' {} 2>/dev/null \
| sort -u)
# Pull
log "[$project] docker compose pull"
if ! docker compose pull 2>&1 | tee -a "$LOG"; then
err "[$project] pull selhal"
FAILED+=("$project")
continue
fi
# Ověř, že se image změnil
AFTER_DIGESTS=$(docker compose config --images 2>/dev/null \
| xargs -I{} docker image inspect --format='{{index .RepoDigests 0}}' "{}" 2>/dev/null \
| sort -u)
CHANGED=0
for d in $AFTER_DIGESTS; do
if ! grep -qx "$d" <<<"$BEFORE_DIGESTS"; then
CHANGED=1
break
fi
done
if [ "$CHANGED" -eq 0 ]; then
log "[$project] žádná změna, přeskakuji up -d"
SKIPPED+=("$project")
continue
fi
# Up -d (vždy background kvůli shell guardu)
log "[$project] docker compose up -d"
if ! docker compose up -d 2>&1 | tee -a "$LOG"; then
err "[$project] up -d selhal"
FAILED+=("$project")
continue
fi
# Počkej na health check
log "[$project] čekám na health check (max ${HEALTH_TIMEOUT}s)"
elapsed=0
healthy=0
while [ "$elapsed" -lt "$HEALTH_TIMEOUT" ]; do
sleep 5
elapsed=$((elapsed + 5))
unhealthy=$(docker compose ps 2>/dev/null \
| tail -n +2 \
| awk '{print $NF}' \
| grep -vE 'healthy|Up' || true)
if [ -z "$unhealthy" ]; then
healthy=1
break
fi
done
if [ "$healthy" -eq 1 ]; then
log "[$project] OK"
UPDATED+=("$project")
else
warn "[$project] běží, ale ne všechny health checks prošly (zkontroluj ručně)"
UPDATED+=("$project:health_unknown")
fi
done
# Prune dangling images (bezpečné)
if [ "$PRUNE_DANGLING" = "1" ]; then
log ""
log "=== DOCKER IMAGE PRUNE -f (dangling only) ==="
docker image prune -f 2>&1 | tee -a "$LOG" || true
fi
# Report
log ""
log "======================================"
log " SHRNUTÍ"
log "======================================"
log "Aktualizováno: ${#UPDATED[@]} projekt(ů)"
for p in "${UPDATED[@]:-}"; do [ -n "$p" ] && log "$p"; done
log "Přeskočeno (beze změny): ${#SKIPPED[@]}"
for p in "${SKIPPED[@]:-}"; do [ -n "$p" ] && log " - $p"; done
if [ "${#FAILED[@]}" -gt 0 ]; then
log "Selhalo: ${#FAILED[@]}"
for p in "${FAILED[@]}"; do err "$p"; done
fi
log ""
log "Log: $LOG"