GitHub Actions schneller machen – Abhängigkeiten und Docker-Layer cachen
Kaltes CI ist langsam: Jede Pipeline lädt Abhängigkeiten, kompiliert immer wieder und baut Docker Images von Grund auf. Mit Caching vermeidest du doppelte Arbeit. Das spart Laufzeit, Kosten und macht deine Builds stabiler.
In diesem Guide lernst du, wie GitHub Actions Caching funktioniert, wie du Keys klug wählst, was der Unterschied zu Artifacts ist und wie du für Node.js, Python, Java und Docker praxistaugliche Caches einrichtest. Schritt für Schritt, ohne Vorwissen, mit kopierbaren Snippets.
Grundlagen: wie der Cache in GitHub Actions arbeitet
Ein Cache speichert Dateien zwischen Workflow-Läufen. Du definierst path (was cachen), key (wann wiederverwenden) und optional restore-keys (Fallbacks). Stimmt der key, gibt es einen Cache-Hit und der Job spart Minuten.
Wichtige Punkte:
- Cache ist nicht gleich Artifact. Artifacts sind Build-Ergebnisse zum Download, Cache ist nur für schnellere Builds gedacht.
- Nutze Lockfiles (package-lock.json, poetry.lock, pom.xml, gradle.lockfile) für stabile Keys.
- Caches sind projektweit nutzbar, können aber per restore-keys auch branchenübergreifend gefunden werden.
Keys und Restore-Keys: die Strategie
Ein guter key repräsentiert den Zustand der Abhängigkeiten. Beispiel: npm-${{ hashFiles('**/package-lock.json') }}. Ändert sich das Lockfile, gibt es Miss, sonst Hit.
restore-keys sind Präfixe, z. B. npm-, um einen nahen Cache zu finden, wenn der exakte Key fehlt. Das ist nützlich bei Branches und Monorepos.
Node.js: npm oder pnpm sauber cachen
schnelles Setup mit setup-node
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
cache-dependency-path: 'package-lock.json'
- run: npm ci
- run: npm test
Vorteile: Automatischer Cache der npm-Daten. Der Key kommt aus dem Lockfile.
individueller Cache mit actions/cache
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
npm-
Hinweis: Cache npm-Store statt node_modules. Mit npm ci bekommst du reproduzierbare Builds.
Python: pip, pip-tools, Poetry
pip Cache
- uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
cache-dependency-path: 'requirements.txt'
- run: pip install -r requirements.txt
Poetry Cache
- uses: actions/cache@v4
with:
path: |
~/.cache/pypoetry
~/.cache/pip
key: poetry-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
poetry-
- run: poetry install --no-interaction --no-ansi
Tipp: Lockfile zwingend nutzen, damit der Cache deterministisch ist.
Java: Maven und Gradle
Maven
- uses: actions/cache@v4
with:
path: ~/.m2/repository
key: maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
maven-
- run: mvn -B -ntp verify
Gradle
- uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
gradle-
- run: ./gradlew build --no-daemon
Best Practice: Wrapper verwenden und Gradle Daemon im CI deaktivieren, um saubere Logs zu bekommen.
Docker: Layer Caching mit Buildx
Buildx und GHA Cache
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: false
tags: myapp:ci
cache-from: type=gha
cache-to: type=gha,mode=max
Die Optionen cache-from/cache-to nutzen den GitHub Actions Cache für Image-Layer. Achte auf eine schlanke Dockerfile-Struktur: abhängigkeitslastige Schritte früh cachen, Quellcode spät kopieren.
Dockerfile Tipp:
- trenne Dependencies und App-Code
- nutze multi-stage builds
- pinne Basisimages für reproduzierbare Layer
Monorepo und Matrix: Caches pro Paket
In Monorepos brauchst du paketspezifische Keys, z. B. npm-appA-${{ hashFiles('apps/appA/package-lock.json') }}. In Matrix-Builds generierst du Keys aus dem Matrix-Namen. So vermeiden sich Jobs gegenseitig zu überschreiben.
Troubleshooting: Cache trifft nicht – was nun
Wenn der Cache nicht greift:
- Prüfe, ob key sich ständig ändert (Zeitstempel vermeiden).
- Stelle sicher, dass die paths korrekt sind und das Tool diese Verzeichnisse nutzt.
- Nutze restore-keys, um nahe Treffer zu erlauben.
- Leere bei Problemen gezielt den Cache, indem du den Key absichtlich änderst (z. B. ein Suffix).
Sicherheit: Lege keine Secrets in Cache-Verzeichnisse. Caches sind für Build-Beschleunigung, nicht für sensible Daten.
Best Practices auf einen Blick
Setze Lockfiles als Key-Basis, cache die Package-Manager-Stores statt der Build-Outputs, halte Keys kurz und stabil, nutze restore-keys für Branch-Fallback, designe Dockerfiles für hohe Layer-Wiederverwendung und dokumentiere deine Cache-Pfade direkt im README des Repos.
Fazit
Mit sauber gesetzten Keys, restore-keys und den richtigen Cache-Pfaden reduzierst du die CI-Laufzeit drastisch. Node, Python, Java und Docker profitieren sofort, wenn du Stores und Layer cachen lässt. Das Ergebnis: schnellere Builds, weniger Kosten, glücklichere Teams.


Hinterlasse einen Kommentar
An der Diskussion beteiligen?Hinterlasse uns deinen Kommentar!