GitLab Pipelines · Workshop Lektion 8 / Container Registry

Ein Docker-Image bauen & pushen

Aus der Tasks-API wird ein deploybares Container-Image – in der GitLab Registry.

Warum das zählt
Getesteter Code muss irgendwie ausgeliefert werden. Der moderne Weg ist ein Container-Image. GitLab bringt eine Container Registry gleich mit – die Pipeline baut das Image und legt es dort ab, bereit zum Deploy. Das ist das Bindeglied zwischen „Tests grün" und „läuft in Produktion".

Kurzer Rückruf

Wie erreicht ein Job einen Begleit-Container?

Docker-in-Docker: Docker baut Docker

Um in einem Job ein Image zu bauen, braucht der Job selbst Zugriff auf einen Docker-Daemon. Den liefert ein Service: docker:dind (Docker-in-Docker). Der Job nutzt das docker-CLI-Image und spricht mit dem dind-Service.

build-image:
  stage: build
  image: docker:27-cli
  services:
    - docker:27-dind
  script:
    # 1) an der GitLab-Registry anmelden – Variablen liefert GitLab automatisch
    - echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" --password-stdin
    # 2) bauen, getaggt mit dem Commit-SHA für Nachvollziehbarkeit
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA -t $CI_REGISTRY_IMAGE:latest .
    # 3) beide Tags pushen
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
    - docker push $CI_REGISTRY_IMAGE:latest

Die Variablen liefert GitLab gratis

CI_REGISTRYHostname der Registry
CI_REGISTRY_IMAGEVoller Image-Pfad dieses Projekts
CI_REGISTRY_USER / _PASSWORDLogin für die Registry (job-gebunden, temporär)
CI_COMMIT_SHORT_SHAKurzer Commit-Hash – ideal als Image-Tag

Du brauchst kein eigenes Geheimnis einzurichten: Login-Daten und Registry-Pfad kommen automatisch aus dem Job-Kontext.

Dein Win Nach diesem Job liegt ein versioniertes Image (: und :latest) in der Registry – nachvollziehbar, wer welchen Stand gebaut hat.

Besonderheiten & Stolperfallen

Mit SHA taggen, nicht nur latest :latest sagt nicht, welcher Code drin ist. Ein Tag mit $CI_COMMIT_SHORT_SHA macht jedes Image eindeutig einem Commit zuordenbar – Gold wert beim Debuggen von „was läuft gerade in Prod?".
dind braucht Privilegien Docker-in-Docker funktioniert nur, wenn der Runner im privileged mode läuft. Auf GitLab.com-Shared-Runnern ist das gegeben; auf self-hosted-Runnern (Puzzle) muss es konfiguriert sein – sonst scheitert der Job am Docker-Daemon.
Alternative ohne dind: kaniko / buildah Wo privileged nicht erlaubt ist, baut man Images ohne Docker-Daemon – etwa mit kaniko oder buildah. Gleiches Ergebnis (Image in der Registry), nur ohne privilegierten dind-Service.
Build nur, wenn nötig Ein Image bei jedem Push zu bauen, kostet Zeit und Speicher. Kombiniere diesen Job sinnvoll mit rules aus Lektion 6 – z. B. nur auf main oder bei Tags.

Übung für Teilnehmende

Übung 1 · Variablen zuordnen

Frage: Welche vordefinierte Variable gehört in docker push ___, um ins richtige Projekt-Repository zu pushen?

Lösung anzeigen

$CI_REGISTRY_IMAGE (plus ein Tag, z. B. :latest). Sie enthält den vollständigen Image-Pfad dieses Projekts in der Registry.

Übung 2 · rules kombinieren

Aufgabe: Lass build-image nur auf dem Default-Branch laufen.

Lösung anzeigen
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

So entsteht ein Image nur für „echte" Stände auf main – nicht für jeden Feature-Push.

Übung 3 · Verstehen

Frage: Warum ist docker:dind hier ein service und nicht das image des Jobs?

Lösung anzeigen

Das Job-image (docker:27-cli) liefert das CLI, mit dem du Befehle tippst. Der service (dind) liefert den Daemon, der die Images tatsächlich baut. Beide zusammen ergeben „Docker im Job" – genau das Service-Muster aus Lektion 7.

Kurz prüfen (aus dem Kopf)

Womit meldet sich der Job an der Registry an?

Warum zusätzlich mit dem Commit-SHA taggen?

Primärquelle zum Lesen GitLab Docs – Build and push container images.
Frag deinen Teacher. Willst du die kaniko-Variante ohne privileged sehen? Sag Bescheid.
← Lektion 7 Lektion 9 · parallel:matrix →