GitLab Runner: Docker-Images bauen

Bauen und pushen Sie Docker-Images direkt aus Ihren GitLab CI/CD-Pipelines mit Ihrem Stackhero Runner und Docker-in-Docker

👋 Willkommen in der Stackhero-Dokumentation!

Stackhero bietet Ihnen eine benutzerfreundliche GitLab Runner Cloud-Lösung, die speziell dafür entwickelt wurde, Ihre GitLab CI/CD-Jobs effizient auszuführen. Das erwartet Sie:

  • Unbegrenzte CI/CD-Minuten: Es gibt keine Abrechnung pro Minute, sodass Ihre Pipelines jederzeit ausgeführt werden können.
  • Mehrere gleichzeitige Jobs: Führen Sie mehrere Jobs parallel aus, um Ihre gesamte Pipeline zu beschleunigen.
  • Der Docker Executor mit Docker-in-Docker-Unterstützung: Optimieren Sie das Erstellen und Pushen Ihrer Container-Images.
  • Kompatibel mit GitLab.com sowie jeder selbst gehosteten GitLab-Instanz.
  • Eine private, dedizierte VM mit schnellen NVMe/SSD-Festplatten für konsistente und zuverlässige Builds.
  • Verfügbar in den Regionen 🇪🇺 Europa und 🇺🇸 USA.

Sparen Sie Zeit: Sie können Ihren ersten GitLab Runner verbinden und Ihre Pipelines in nur wenigen Minuten starten!

Wenn Sie einen Stackhero GitLab Runner verwenden, werden Jobs mit dem Docker Executor ausgeführt. Das bedeutet, dass jeder Job in einem frischen Container startet, der auf dem von Ihnen angegebenen image basiert. Möchten Sie im Rahmen Ihrer Pipeline eigene Docker-Images bauen, können Sie Docker-in-Docker (DinD) nutzen. Mit dieser Konfiguration läuft ein Docker-Daemon parallel zu Ihrem Job, sodass Sie Befehle wie docker build und docker push direkt innerhalb Ihrer Pipeline ausführen können.

Ein großer Vorteil dabei ist, dass Ihr Runner über unbegrenzte CI/CD-Minuten verfügt. Sie können Images so oft bauen, wie Sie möchten. Außerdem befindet sich Ihr Build-Cache auf der dedizierten Festplatte des Runners, sodass wiederholte Builds vorherige Layer wiederverwenden können und Ihre Pipelines dadurch deutlich schneller abgeschlossen werden.

Hier finden Sie ein Beispiel für eine .gitlab-ci.yml, die Sie zu Ihrem Repository hinzufügen können. Diese Konfiguration baut das Dockerfile, das sich im Root-Verzeichnis Ihres Projekts befindet:

build-image:
  stage: build
  image: docker:27
  services:
    - docker:27-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  before_script:
    - docker info
  script:
    # Ersetzen Sie "my-image" durch den gewünschten Namen:
    - docker build -t my-image .
    # Optional können Sie einen kurzen Smoke-Test auf dem gebauten Image ausführen:
    # - docker run --rm my-image /path/to/tests

In dieser Konfiguration startet der Service docker:27-dind den Docker-Daemon. Die Variable DOCKER_TLS_CERTDIR: "/certs" aktiviert eine sichere TLS-Verbindung zwischen Ihrem Job und dem Docker-Daemon.

GitLab stellt mehrere vordefinierte Variablen (CI_REGISTRY, CI_REGISTRY_USER, CI_REGISTRY_PASSWORD, CI_REGISTRY_IMAGE) bereit, sodass Ihre Pipeline sich anmelden und Images in die Container Registry des Projekts pushen kann, ohne dass zusätzliche Secrets benötigt werden.

Hier ein Beispiel-Job, der Ihr Image baut und pusht:

build-and-push:
  stage: build
  image: docker:27
  services:
    - docker:27-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
  script:
    - docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" .
    - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
    # Wenn Sie sich auf dem Default-Branch befinden, können Sie zusätzlich "latest" taggen und pushen:
    - |
      if [ "$CI_COMMIT_BRANCH" = "$CI_DEFAULT_BRANCH" ]; then
        docker tag "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" "$CI_REGISTRY_IMAGE:latest"
        docker push "$CI_REGISTRY_IMAGE:latest"
      fi

Wenn Sie Ihre Images in eine andere Registry (wie Docker Hub oder eine private Registry) pushen möchten, können Sie die Zugangsdaten als CI/CD-Variablen speichern und diese wie oben mit docker login verwenden.

Da die Festplatte Ihres Runners zwischen den Pipelines bestehen bleibt, können Sie Builds beschleunigen, indem Sie vorherige Image-Layer als Cache wiederverwenden. So können Sie das einrichten:

build-cached:
  stage: build
  image: docker:27
  services:
    - docker:27-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
  script:
    # Versuchen Sie, das neueste Image zu pullen, um den Cache zu initialisieren (kein Problem, falls es noch nicht existiert):
    - docker pull "$CI_REGISTRY_IMAGE:latest" || true
    - docker build --cache-from "$CI_REGISTRY_IMAGE:latest" -t "$CI_REGISTRY_IMAGE:latest" .
    - docker push "$CI_REGISTRY_IMAGE:latest"

Mit dieser Methode werden Ihre Pipelines im Laufe der Zeit schneller, da Docker's Layer-Caching optimal genutzt wird.

Ihr Tarif bestimmt, wie viele Jobs gleichzeitig ausgeführt werden können. Jobs innerhalb derselben Stage starten parallel, bis zur maximalen Parallelitätsgrenze. Das bedeutet, dass eine Stage mit mehreren unabhängigen Jobs abgeschlossen ist, sobald der langsamste Job fertig ist – die Jobs laufen also nicht nacheinander, sondern parallel.

Hier ein einfaches Beispiel:

stages:
  - test

unit:
  stage: test
  image: node:22
  script: npm run test:unit

integration:
  stage: test
  image: node:22
  script: npm run test:integration

e2e:
  stage: test
  image: node:22
  script: npm run test:e2e

Wenn Sie Ihre Parallelität auf 3 oder mehr setzen, laufen die Jobs unit, integration und e2e alle gleichzeitig.

Wenn Sie sich noch tiefer mit dem Thema Docker-Image-Builds in CI beschäftigen möchten, empfehlen wir die offizielle GitLab-Dokumentation.