338 lines
9.2 KiB
Markdown
338 lines
9.2 KiB
Markdown
# Docker Compose Auto-Updater
|
||
|
||
<p align="center">
|
||
<img src="./images/composeupdater.png" alt="Logo" width="200">
|
||
</p>
|
||
|
||
---
|
||
|
||
> 🔧 Automatisches Update von Docker-Compose-Stacks mit feingranularer Steuerung per Labels
|
||
|
||
## 🚀 Features
|
||
|
||
- 🔄 **Stack-basiertes Update**
|
||
Aktualisiert komplette Docker-Compose Stacks strukturiert und kontrolliert
|
||
- 🧪 **Dry-Run Modus**
|
||
Zeigt an, was passieren würde, ohne Änderungen durchzuführen
|
||
- 📲 **ntfy Benachrichtigungen**
|
||
Push-Notifications über ntfy bei Updates, Fehlern oder Status
|
||
- ⚙️ **Service-Modi** (per Label steuerbar)
|
||
Einzelne Container oder komplette Stacks gezielt vom Update ausschließen
|
||
- 🗑️ **Prune Funktion**
|
||
Entfernt nicht mehr benötigte Images/Container automatisch
|
||
|
||
|
||
---
|
||
|
||
## 📂 Voraussetzungen
|
||
|
||
- Docker + Docker Compose (v2)
|
||
- Bash
|
||
- jq
|
||
- Optional: ntfy Server
|
||
|
||
---
|
||
|
||
## 🧠 Funktionsweise
|
||
|
||
1. Alle `*compose*.yml` Dateien werden rekursiv gefunden
|
||
2. Verarbeitung erfolgt alphabetisch (deterministische Reihenfolge)
|
||
3. Für jeden Stack:
|
||
- Compose-Konfiguration wird ausgewertet (`docker compose config`)
|
||
- Services und deren Images werden ermittelt
|
||
- Für jedes Image:
|
||
- Image wird bei Bedarf gepullt (maximal einmal pro Image und Stack, Cache-basiert)
|
||
- Lokale Image-ID wird ermittelt
|
||
- Image-ID des vorhandenen Containers wird ermittelt (auch für gestoppte Container)
|
||
4. Entscheidungslogik:
|
||
- ❌ Container existiert nicht → kein Update (nur Definition vorhanden)
|
||
- ❌ Image-ID unverändert → kein Update
|
||
- ✅ Image-ID hat sich geändert → Update erkannt
|
||
5. Wenn mindestens ein Service ein Update hat:
|
||
- **Einzelcontainer:**
|
||
- gezieltes Update nur dieses Services (`docker compose up -d <service>`)
|
||
- **Mehrere Services:**
|
||
- kompletter Stack wird neu deployed (`docker compose up -d`)
|
||
- **Optional**
|
||
- feste Wartezeit nach dem Deploy (`REDEPLOY_WAIT`)
|
||
- anschließendes Warten auf erfolgreiche Healthchecks (`REDEPLOY_WAIT_HEALTHY`)
|
||
6. Sonderverhalten:
|
||
- Gestoppte Container werden ebenfalls geprüft und bei Updates berücksichtigt
|
||
- Gestoppte Container werden nach dem Update optional wieder gestoppt
|
||
- Service-Verhalten wird vollständig über Labels gesteuert (`composeupdater.mode`)
|
||
- Je nach Modus werden Services:
|
||
- komplett ignoriert (`ignore`)
|
||
- nur überwacht (`notify-only`)
|
||
- oder automatisch aktualisiert (`update`)
|
||
|
||
|
||
---
|
||
|
||
## ⚙️ Service-Modi (per Label steuerbar)
|
||
|
||
Du kannst das Verhalten einzelner Services oder ganzer Stacks über Labels steuern:
|
||
|
||
```yml
|
||
labels:
|
||
- composeupdater.mode=update
|
||
```
|
||
|
||
### 📊 Übersicht
|
||
|
||
| Mode | Pull | Compare | Update | ntfy |
|
||
| ----------- | ---- | ------- | ------ | ---- |
|
||
| update | ✅ | ✅ | ✅ | ✅ |
|
||
| notify-only | ✅ | ✅ | ❌ | ✅ |
|
||
| ignore | ❌ | ❌ | ❌ | ❌ |
|
||
|
||
|
||
### 🧠 Erklärung der Modi
|
||
|
||
🔄 `update` (**Standard**)
|
||
- Images werden gepullt
|
||
- Lokales Image wird mit dem Container verglichen
|
||
- Bei Änderungen wird der Service bzw. Stack aktualisiert
|
||
- ntfy-Benachrichtigung wird gesendet
|
||
|
||
|
||
🔔 `notify-only`
|
||
- Image wird gepullt (für Vergleich notwendig)
|
||
- Es wird geprüft, ob ein Update verfügbar ist
|
||
- Kein Container-Update / kein Restart
|
||
- ntfy informiert über verfügbare Updates
|
||
|
||
|
||
🚫 `ignore`
|
||
- Service wird komplett ignoriert
|
||
- Kein Pull
|
||
- Kein Vergleich
|
||
- Kein Update
|
||
- Keine Benachrichtigung
|
||
|
||
|
||
### 🧩 Beispiele
|
||
|
||
#### Service ausschließen (komplett ignorieren)
|
||
|
||
```yml
|
||
services:
|
||
db:
|
||
image: postgres:15
|
||
labels:
|
||
- composeupdater.mode=ignore
|
||
```
|
||
|
||
#### Nur Benachrichtigung, kein automatisches Update
|
||
|
||
```yml
|
||
services:
|
||
app:
|
||
image: myapp:latest
|
||
labels:
|
||
- composeupdater.mode=notify-only
|
||
```
|
||
|
||
#### Explizit Standardverhalten setzen
|
||
|
||
```yml
|
||
services:
|
||
web:
|
||
image: nginx:latest
|
||
labels:
|
||
- composeupdater.mode=update
|
||
```
|
||
|
||
---
|
||
|
||
## 🗑️ Prune / Cleanup
|
||
|
||
Nach Abschluss der Updates kann optional ein Docker Cleanup durchgeführt werden.
|
||
Dabei werden ungenutzte Ressourcen entfernt:
|
||
|
||
- `docker image prune`
|
||
→ entfernt ungenutzte („dangling“) Images
|
||
|
||
- `docker image prune -a`
|
||
→ entfernt alle Images, die von keinem Container verwendet werden
|
||
|
||
- `docker container prune`
|
||
→ entfernt gestoppte Container
|
||
|
||
- `docker volume prune`
|
||
→ entfernt ungenutzte Volumes
|
||
|
||
- `docker network prune`
|
||
→ entfernt ungenutzte Netzwerke
|
||
|
||
---
|
||
|
||
## 🔔 ntfy
|
||
|
||
| Zustand | Priorität |
|
||
|----------------------|----------|
|
||
| ✔️ Keine Updates | 1 |
|
||
| 🔄 Updates vorhanden | 3 |
|
||
| ❌ Fehler | 5 |
|
||
|
||
### Anzeigebeispiel
|
||
|
||
<p align="left">
|
||
<img src="./images/ntfy.png" alt="Logo" width="400">
|
||
</p>
|
||
|
||
---
|
||
|
||
## ⚙️ Konfiguration (`config.conf`)
|
||
|
||
```bash
|
||
# ==========================================================
|
||
# DOCKER COMPOSE UPDATER - CONFIG
|
||
# ==========================================================
|
||
|
||
|
||
# ----------------------------------------------------------
|
||
# PATH
|
||
# ----------------------------------------------------------
|
||
|
||
# Basisverzeichnis der Stacks [ String ]
|
||
PATH_COMPOSE_DIR="/pfad/zu/deinen/stacks"
|
||
|
||
# Compose-Dateiname [ String ]
|
||
PATH_COMPOSE_PATTERN="*compose*.yml"
|
||
|
||
|
||
# ----------------------------------------------------------
|
||
# LOG
|
||
# ----------------------------------------------------------
|
||
|
||
# Log-Datei [ String ]
|
||
LOG_FILE="/pfad/zum/log/update.log"
|
||
|
||
# Log-Level [ DEBUG | INFO | WARN | ERROR ]
|
||
LOG_LEVEL="INFO"
|
||
|
||
|
||
# ----------------------------------------------------------
|
||
# UPDATE
|
||
# ----------------------------------------------------------
|
||
|
||
# Nur Simulation, keine Änderungen [ true | false ]
|
||
UPDATE_DRY_RUN_ENABLED=false
|
||
|
||
# Gestoppte Container updaten [ true | false ]
|
||
UPDATE_INCLUDE_STOPPED=true
|
||
|
||
# Danach wieder starten [ true | false ]
|
||
UPDATE_START_STOPPED=false
|
||
|
||
|
||
# ----------------------------------------------------------
|
||
# REDEPLOY
|
||
# ----------------------------------------------------------
|
||
|
||
# Feste Wartezeit nach Redeploy [ Number ]
|
||
REDEPLOY_WAIT=45
|
||
|
||
# Warten bis Container healthy sind [ true | false ]
|
||
REDEPLOY_WAIT_HEALTHY=true
|
||
|
||
# Timeout in Sekunden für healthy Check [ Number ]
|
||
REDEPLOY_WAIT_HEALTHY_TIMEOUT=60
|
||
|
||
|
||
# ----------------------------------------------------------
|
||
# NTFY SETTINGS
|
||
# ----------------------------------------------------------
|
||
|
||
# NTFY Zusammenfassung senden [ true | false ]
|
||
NTFY_ENABLED=true
|
||
|
||
# Server URL [ String ]
|
||
NTFY_URL="https://ntfy.example.com/topic"
|
||
|
||
# Token [ String ]
|
||
NTFY_TOKEN="DEIN_TOKEN"
|
||
|
||
# Titel mitsenden (optional) [ String ]
|
||
NTFY_TITLE="Autoupdate Report ($(hostname))"
|
||
|
||
# Tags mitsenden (optional) [ String ]
|
||
NTFY_TAGS="docker,update"
|
||
|
||
# Icon mitsenden (optional) [ String ]
|
||
NTFY_IMAGE_URL="http://dein-server/host-icon.png"
|
||
|
||
# Nur senden wenn Updates vorhanden [ true | false ]
|
||
NTFY_ONLY_ON_CHANGES=false
|
||
|
||
# Versionsnummern anzeigen [ true | false ]
|
||
NTFY_SHOW_VERSIONS=true
|
||
|
||
|
||
# ----------------------------------------------------------
|
||
# DOCKER CLEANUP
|
||
# ----------------------------------------------------------
|
||
|
||
# Prune Befehle ausführen [ true | false ]
|
||
CLEANUP_ENABLED=true
|
||
|
||
# Nur nach erfolgten Updates ausführen [ true | false ]
|
||
CLEANUP_ONLY_ON_UPDATE=true
|
||
|
||
# Images löschen [ true | false ]
|
||
CLEANUP_IMAGES_ENABLED=true
|
||
|
||
# Image-Prune Modus [ dangling | unused ]
|
||
CLEANUP_IMAGES_MODE="unused"
|
||
|
||
# Container löschen [ true | false ]
|
||
CLEANUP_CONTAINERS_ENABLED=true
|
||
|
||
# Volumes löschen [ true | false ]
|
||
CLEANUP_VOLUMES_ENABLED=false
|
||
|
||
# Networks löschen [ true | false ]
|
||
CLEANUP_NETWORKS_ENABLED=true
|
||
```
|
||
|
||
---
|
||
|
||
## ▶️ Nutzung
|
||
|
||
```bash
|
||
chmod +x script.sh
|
||
./script.sh
|
||
```
|
||
|
||
---
|
||
|
||
## 📄 Beispiel Ausgabe
|
||
|
||
```
|
||
🔍 Prüfe Stack: rss
|
||
├─ read (phpdockerio/readability-js-server) [Mode: 🔄 update]
|
||
├─ merc (wangqiru/mercury-parser-api) [Mode: 🔄 update]
|
||
├─ full-text-rss (heussd/fivefilters-full-text-rss:latest) [Mode: 🔄 update]
|
||
├─ rss-bridge (rssbridge/rss-bridge:latest) [Mode: 🔄 update]
|
||
⬆️ UPDATE
|
||
alt: rssbridge/rss-bridge:latest@sha256:55215923cf81b2fa6fbb7ecc1bd2555405f4fc06029ae9876e91164a735c7b9d
|
||
neu: rssbridge/rss-bridge:latest@sha256:f3f0218c8b075cbc7c559c8e6852888e95fa6d68258436da6195efc5ab98b025
|
||
└─ freshrss (freshrss/freshrss:latest) [Mode: 🔄 update]
|
||
♻️ Stack wird neu deployt (Trigger: rss-bridge)
|
||
⏳ Deploy läuft...
|
||
✅ Stack erfolgreich aktualisiert
|
||
💤 Warte 60s nach Deploy
|
||
ℹ️ Keine Healthchecks definiert → überspringe warten
|
||
🕒 Dauer: 18s
|
||
|
||
|
||
→ Prüfe Stack: tinymediamanager
|
||
└─ tinymediamanager [Mode: 🚫 ignore]
|
||
🕒 Dauer: 1s
|
||
```
|
||
|
||
---
|
||
|
||
## ⚠️ Hinweise
|
||
|
||
Wird in einem Stack ein Container aktualisiert, wird anschließend der gesamte Stack neu gestartet, sofern er mehr als einen Container enthält. Dadurch wird sichergestellt, dass alle Abhängigkeiten wieder gemäß der `docker-compose.yml` ausgeführt werden. |