So erstellen Sie Docker-Images in einer GitLab-CI-Pipeline

0
466

Ein häufiger Anwendungsfall für CI-Pipelines ist das Erstellen der von Ihnen erstellten Docker-Images&#8217 ;ll verwenden, um Ihre Anwendung bereitzustellen. GitLab CI ist dafür eine gute Wahl, da es einen integrierten Pull-Proxy-Dienst unterstützt, was schnellere Pipelines bedeutet, und eine integrierte Registrierung zum Speichern Ihrer erstellten Images.

In diesem Leitfaden zeigen wir Ihnen, wie Sie Docker-Builds einrichten, die beide oben genannten Funktionen verwenden. Die Schritte, die Sie ausführen müssen, variieren leicht je nach GitLab Runner-Executor-Typ, den Sie für Ihre Pipeline verwenden werden. Wir behandeln die Shell- und Docker-Executoren unten.

Building With the Shell Executor

Wenn Sie’ Wenn Sie den Shell-Executor verwenden, stellen Sie sicher, dass Docker auf dem Computer installiert ist, der Ihren Runner hostet. Der Executor funktioniert, indem er reguläre Shell-Befehle unter Verwendung der Docker-Binärdatei auf dem Host des Runners ausführt.

Gehen Sie zum Git-Repository für das Projekt, für das Sie Images erstellen möchten. Erstellen Sie eine .gitlab-ci.yml-Datei im Stammverzeichnis des Repositorys. Diese Datei definiert die GitLab-CI-Pipeline, die ausgeführt wird, wenn Sie Änderungen an Ihr Projekt übertragen.

Fügen Sie der Datei folgenden Inhalt hinzu:

stages: – build docker_build: stage: build script: – docker build -t example.com/example-image:latest . – docker push example.com/example-image:latest

Diese vereinfachte Konfiguration reicht aus, um die Grundlagen von Pipeline-gestützten Image-Builds zu demonstrieren. GitLab klont Ihr Git-Repository automatisch in die Build-Umgebung, sodass beim Ausführen von Docker Build die Docker-Datei Ihres Projekts verwendet und der Inhalt des Repositorys als Build-Kontext verfügbar gemacht wird.

Werbung

Nachher Wenn der Build abgeschlossen ist, können Sie das Image per Docker in Ihre Registrierung übertragen. Andernfalls wäre es nur für die lokale Docker-Installation verfügbar, die den Build ausgeführt hat. Wenn Sie eine private Registrierung verwenden, führen Sie zuerst docker login aus, um die richtigen Authentifizierungsdetails bereitzustellen:

script: – docker login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWORD

Definieren Sie die Werte der beiden Berechtigungsvariablen, indem Sie zu Einstellungen > CI/CD > Variablen in der GitLab-Web-UI. Klicken Sie auf das blaue “Variable hinzufügen” Schaltfläche, um eine neue Variable zu erstellen und einen Wert zuzuweisen. GitLab stellt diese Variablen in der Shell-Umgebung zur Verfügung, die zum Ausführen Ihres Jobs verwendet wird.

Building with the Docker Executor

Der Docker-Executor von GitLab Runner wird häufig verwendet, um eine vollständig saubere Umgebung für jeden Job bereitzustellen. Der Job wird in einem isolierten Container ausgeführt, sodass auf die Docker-Binärdatei auf dem Runner-Host nicht zugegriffen werden kann.

Der Docker-Executor bietet Ihnen zwei mögliche Strategien zum Erstellen Ihres Images: Verwenden Sie entweder Docker-in-Docker oder binden Sie den Docker-Socket des Hosts in die Build-Umgebung des Runners ein. Anschließend verwenden Sie das offizielle Docker-Container-Image als Job-Image und machen den Docker-Befehl in Ihrem CI-Skript verfügbar.

Docker-in-Docker

Die Verwendung von Docker-in-Docker (DinD) zum Erstellen Ihrer Images gibt Ihnen eine vollständig isolierte Umgebung für jeden Job. Der Docker-Prozess, der den Build ausführt, ist ein untergeordnetes Element des Containers, den GitLab Runner auf dem Host erstellt, um den CI-Job auszuführen.

Sie müssen Ihren GitLab Runner Docker-Executor mit aktiviertem privilegiertem Modus registrieren, um DinD verwenden zu können . Fügen Sie das Flag –docker-privileged hinzu, wenn Sie Ihren Runner registrieren:

sudo gitlab-runner register -n –url https://example.com –registration-token $GITLAB_REGISTRATION_TOKEN –executor docker –description “Docker Runner” –docker-image “docker:20.10” –docker-volumes “/certs/client” –docker-privileged Advertisement

Fügen Sie in Ihrer CI-Pipeline das docker:dind-Image als Dienst hinzu. Dadurch wird Docker als separates Image verfügbar, das mit dem Job-Image verknüpft ist. Sie können den docker-Befehl verwenden, um Images mithilfe der Docker-Instanz im docker:dind-Container zu erstellen.

services: – docker:dind docker_build: stage: build image: docker:latest script: – docker build -t Beispielbild:neueste .

Durch die Verwendung von DinD erhalten Sie vollständig isolierte Builds, die sich gegenseitig oder Ihren Host nicht beeinflussen können. Der Hauptnachteil ist das kompliziertere Caching-Verhalten: Jeder Job erhält eine neue Umgebung, in der zuvor erstellte Layer nicht zugänglich sind. Sie können dies teilweise beheben, indem Sie versuchen, die vorherige Version Ihres Images vor dem Erstellen abzurufen, und dann das Flag –cache-from build verwenden, um die Ebenen des abgerufenen Abbilds als Cache-Quelle verfügbar zu machen:

docker_build : stage: build image: docker:latest script: – docker pull $CI_REGISTRY_IMAGE:latest || true – docker build –cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:latest .

Socket-Bind-Halterungen

Das Mounten des Docker-Sockets Ihres Hosts in die Umgebung Ihres Jobs ist eine alternative Option, wenn Sie den Docker-Executor verwenden. Dadurch erhalten Sie nahtloses Caching und es ist nicht mehr erforderlich, den docker:dind-Dienst zu Ihrer CI-Konfiguration hinzuzufügen.

Um dies einzurichten, registrieren Sie Ihren Runner mit einem Docker-Volumes-Flag, das die Hosts bindet Docker-Socket zu /var/run/docker.sock innerhalb von Job-Containern:

sudo gitlab-runner register -n –url https://example.com –registration-token $GITLAB_REGISTRATION_TOKEN –executor docker –description “Docker Runner” –docker-image “docker:20.10” –docker-volumes /var/run/docker.sock:/var/run/docker.sock

Jetzt können Jobs, die mit dem Docker-Image ausgeführt werden, die Docker-Binärdatei wie gewohnt verwenden. Operationen werden tatsächlich auf Ihrem Host-Rechner ausgeführt und werden zu Geschwistern des Job-Containers statt zu Kindern.

Dies ähnelt im Grunde der Verwendung des Shell-Executors mit der Docker-Installation Ihres Hosts. Bilder werden auf dem Host gespeichert, was die nahtlose Verwendung des regulären Docker-Build-Layer-Cachings erleichtert.

Werbung

Während dieser Ansatz zu höherer Leistung, weniger Konfiguration und keiner der Einschränkungen von DinD führen kann, bringt er seine eigenen einzigartigen Probleme mit sich. Am wichtigsten sind die Auswirkungen auf die Sicherheit: Jobs könnten beliebige Docker-Befehle auf Ihrem Runner-Host ausführen, sodass ein bösartiges Projekt in Ihrer GitLab-Instanz möglicherweise docker run -it schädliches Bild:neueste oder docker rm -f $(docker ps -a ) mit verheerenden Folgen.

GitLab warnt auch davor, dass die Socket-Bindung Probleme verursachen kann, wenn Jobs gleichzeitig ausgeführt werden. Dies tritt auf, wenn Sie sich darauf verlassen, dass Container mit bestimmten Namen erstellt werden. Wenn zwei Instanzen eines Jobs parallel ausgeführt werden, schlägt die zweite fehl, da der Containername bereits auf Ihrem Host vorhanden ist.

Sie sollten stattdessen DinD verwenden, wenn Sie erwarten, dass eines dieser Probleme Probleme bereiten wird. Während DinD nicht mehr allgemein empfohlen wird, kann es für öffentlich zugängliche GitLab-Instanzen sinnvoller sein, die gleichzeitig CI-Jobs ausführen.

Pushen von Bildern in die GitLab-Registrierung

GitLab-Projekte haben die Option einer integrierten Registrierung, die Sie zum Speichern Ihrer Bilder verwenden können. Sie können den Inhalt der Registrierung anzeigen, indem Sie zu Pakete & Register > Container Registry in der Seitenleiste Ihres Projekts. Wenn Sie diesen Link nicht sehen, aktivieren Sie die Registrierung, indem Sie zu Einstellungen > Allgemein > Sichtbarkeit, Projekt, Funktionen & Berechtigungen und Aktivierung der “Container Registry” umschalten.

 

GitLab legt automatisch Umgebungsvariablen in Ihren CI-Jobs fest mit denen Sie auf die Containerregistrierung Ihres Projekts verweisen können. Passen Sie den Skriptabschnitt an, um sich bei der Registrierung anzumelden, und übertragen Sie Ihr Image:

script: – docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY – docker build -t $CI_REGISTRY_IMAGE:latest . – Docker-Push $CI_REGISTRY_IMAGE:latest

GitLab generiert einen sicheren Satz von Anmeldeinformationen für jeden Ihrer CI-Jobs. Die Umgebungsvariable $CI_JOB_TOKEN enthält ein Zugriffstoken, mit dem der Job als Benutzer gitlab-ci-token eine Verbindung zur Registrierung herstellen kann. Die Registrierungsserver-URL ist als $CI_REGISTRY verfügbar.

Anzeige

Die letzte Variable, $CI_REGISTRY_IMAGE, stellt den vollständigen Pfad zur Containerregistrierung Ihres Projekts bereit. Dies ist eine geeignete Basis für Ihre Image-Tags. Sie können diese Variable erweitern, um Unterrepositorys zu erstellen, z. B. $CI_REGISTRY_IMAGE/production/api:latest.

 

Andere Docker-Clients können Images aus der Registrierung abrufen, indem sie sich mit einem Zugriffstoken authentifizieren. Sie können diese in den Einstellungen Ihres Projekts > Zugriff auf den Token-Bildschirm. Fügen Sie den Bereich read_registry hinzu und verwenden Sie dann die angezeigten Anmeldeinformationen, um sich über Docker bei der Registrierung Ihres Projekts anzumelden.

Using GitLab’s Dependency Proxy

h2>

Der Dependency Proxy von GitLab bietet eine Caching-Schicht für die Upstream-Images, die Sie aus Docker Hub ziehen. Es hilft Ihnen, die Ratenbegrenzungen von Docker Hub einzuhalten, indem es nur den Inhalt von Bildern abruft, wenn sie sich tatsächlich geändert haben. Dadurch wird auch die Leistung Ihrer Builds verbessert.

Der Abhängigkeits-Proxy wird auf der GitLab-Gruppenebene aktiviert, indem Sie zu Einstellungen > Pakete & Register > Abhängigkeits-Proxy. Sobald es aktiviert ist, stellen Sie Bildreferenzen in Ihrer .gitlab-ci.yml-Datei $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX voran, um sie durch den Proxy zu ziehen:

docker_build: stage: build image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/docker:latest services: – name: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/docker:dind alias: docker

Das ist alles! GitLab Runner meldet sich automatisch bei der Dependency-Proxy-Registrierung an, sodass Sie Ihre Anmeldeinformationen nicht manuell eingeben müssen.

GitLab speichert Ihre Bilder jetzt im Cache, was Ihnen eine verbesserte Leistung sowie Ausfallsicherheit bei Netzwerkausfällen bietet. Beachten Sie, dass auch die Dienstdefinition angepasst werden musste – Umgebungsvariablen funktionieren nicht mit dem zuvor verwendeten Inline-Formular, daher muss der vollständige Bildname angegeben werden, dann ein Befehlsalias, auf den in Ihrem Skriptabschnitt verwiesen werden soll.

Werbung

Während wir jetzt den Proxy für Images eingerichtet haben, die direkt von unseren Jobphasen verwendet werden, ist noch mehr Arbeit erforderlich, um Unterstützung für das Basisimage in der zu erstellenden Docker-Datei hinzuzufügen. Eine normale Anweisung wie diese geht nicht über den Proxy:

FROM ubuntu:latest

Um dieses letzte Stück hinzuzufügen, verwenden Sie die Build-Argumente von Docker, um die Abhängigkeits-Proxy-URL beim Durchlaufen verfügbar zu machen Dockerfile:

ARG GITLAB_DEPENDENCY_PROXY FROM ${GITLAB_DEPENDENCY_PROXY}/ubuntu:latest

Ändern Sie dann Ihren Docker-Build-Befehl, um den Wert der Variablen zu definieren:

Skript: > – docker build –build-arg GITLAB_DEPENDENCY_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX} -t example-image:latest .

Jetzt wird auch Ihr Basis-Image durch den Abhängigkeits-Proxy gezogen.

Zusammenfassung

Docker-Image-Builds lassen sich einfach in Ihre GitLab-CI-Pipelines integrieren. Nach der anfänglichen Runner-Konfiguration sind Docker-Build- und Docker-Push-Befehle im Skriptabschnitt Ihres Jobs alles, was Sie brauchen, um ein Image mit der Docker-Datei in Ihrem Repository zu erstellen. Die integrierte Containerregistrierung von GitLab bietet Ihnen privaten Speicherplatz für die Bilder Ihres Projekts.

Über grundlegende Builds hinaus lohnt es sich, den Abhängigkeits-Proxy von GitLab zu integrieren, um die Leistung zu beschleunigen und zu vermeiden, dass Docker Hub-Ratenbegrenzungen erreicht werden. Sie sollten auch die Sicherheit Ihrer Installation überprüfen, indem Sie prüfen, ob Ihre ausgewählte Methode nicht vertrauenswürdigen Projekten erlaubt, Befehle auf Ihrem Runner-Host auszuführen. Obwohl es seine eigenen Probleme mit sich bringt, ist Docker-in-Docker der sicherste Ansatz, wenn Ihre GitLab-Instanz öffentlich zugänglich ist oder von einer großen Benutzerbasis aufgerufen wird.