Pinned Versions vs latest - wie man den richtigen Mittelweg findet

Pinned Versions vs latest - wie man den richtigen Mittelweg findet

latest ist unvorhersehbar, zu stark gepinnte Versionen verpassen Sicherheitsupdates – der richtige Mittelweg ist eine Frage der Strategie.

Das Problem mit latest

# Gefährlich in Produktion
image: nginx:latest

latest zeigt auf den neuesten Build zum Zeitpunkt des Pulls. Ein docker compose pull nächste Woche kann einen Breaking Change mitbringen. Auf verschiedenen Servern kann dieselbe Compose-Datei unterschiedliche Versionen ausführen.

Das Problem mit zu stark gepinnten Versionen

# Zu restriktiv
image: nginx:1.25.3

Sicherheitslücken in nginx 1.25.3 werden nicht automatisch behoben. Man muss jede Patch-Version manuell aktualisieren und weiss oft nicht wann eine neue rauskommt.

Der Mittelweg: Minor-Version pinnen

# Gut: bekommt Patch-Updates, keine Breaking Changes
image: nginx:1.25
image: postgres:16
image: node:20-alpine
  • Die meisten Projekte folgen Semantic Versioning: Major.Minor.Patch.
  • Patch-Updates (1.25.3 → 1.25.4): Nur Bug-Fixes, sichere automatische Updates
  • Minor-Updates (1.25 → 1.26): Neue Features, abwärtskompatibel
  • Major-Updates (1.x → 2.x): Breaking Changes möglich

Durch Pinnen auf die Minor-Version (nginx:1.25) erhält man Patch-Updates automatisch ohne Breaking Changes zu riskieren.

Digest-Pinning: Maximale Reproduzierbarkeit

# Byte-für-Byte identisch, immer
image: nginx@sha256:a480a496da64e3f8b8e5c89fa87958b7f37cfbd87cb64d41b90a30bb65a5ae0c

Der Digest ist der Hash des Image-Inhalts. Er ändert sich nie. Damit ist jeder Build identisch – ideal für kritische Produktivumgebungen.

# Digest eines Images ermitteln
docker inspect nginx:1.25 --format '{{index .RepoDigests 0}}'
# nginx@sha256:a480a496...

Nachteil: Sicherheitsupdates bekommt man nie automatisch. Man muss den Digest manuell aktualisieren.

Tagging-Strategie verschiedener Projekte

Nicht alle Images folgen Semantic Versioning – das muss man pro Image prüfen:

# Docker Hub: Tags eines Images anzeigen
curl -s https://hub.docker.com/v2/repositories/library/nginx/tags/ | python3 -m json.tool | grep name

linuxserver.io Images: Nutzen oft Datumsbasierte Tags (latest, nightly) – hier ist latest relativ sicher da sie Changelogs pflegen.

Bitnami: Nutzen vollständige Versionsnummern, sehr empfehlenswert zum pinnen.

Offiziell Postgres: postgres:16 = aktuellste Postgres 16.x, sicheres pinnen.

Empfehlung nach Umgebung

| Umgebung | Empfehlung | Beispiel |
|---|---|---|
| Produktion | Minor-Version + Renovate für PRs | nginx:1.25 |
| Staging | Minor-Version | nginx:1.25 |
| Development | Minor oder latest | nginx:latest |
| CI/CD Reproduzierbarkeit | Digest | nginx@sha256:... |

Mit Renovate automatisch PRs öffnen

// renovate.json
{
  "packageRules": [
    {
      "matchDatasources": ["docker"],
      "matchUpdateTypes": ["minor", "patch"],
      "automerge": false
    }
  ]
}

Renovate erkennt neue Minor/Patch-Releases und öffnet PRs – man reviewed den Changelog, merged, und docker compose pull erledigt den Rest.