Besser spĂ€t als nie. Oder wie wir fast einen ernsthaften Fehler gemacht hĂ€tten, weil wir keine UnterstĂŒtzung fĂŒr gĂ€ngige Dockerfiles zum Erstellen von Anwendungsimages hatten.

Es geht um â ein GitOps-Tool, das sich in jedes CI/CD-System integriert und die gesamte Lebenszyklusverwaltung von Anwendungen ermöglicht, indem es:
- Images erstellt und veröffentlicht,
- Anwendungen in Kubernetes bereitstellt,
- nicht mehr benötigte Images durch spezielle Richtlinien entfernt.
Die Philosophie des Projekts besteht darin, grundlegende Werkzeuge in ein einheitliches System zu integrieren, das DevOps-Ingenieuren die Kontrolle ĂŒber Anwendungen gibt. Wo möglich, sollten bereits bestehende Tools (wie Helm und Docker) verwendet werden. Wenn jedoch keine Lösung fĂŒr eine bestimmte Aufgabe existiert, können wir alles Notwendige dafĂŒr schaffen und unterstĂŒtzen.
Vorgeschichte: unser Image-Builder
So kam es, dass wir fĂŒr den Image-Builder in werf einen gewohnten Dockerfile vermissten. Wenn wir kurz auf die Geschichte des Projekts zurĂŒckblicken, wird sichtbar, dass dieses Problem bereits in den ersten Versionen von werf (damals noch ).
auftrat. Als wir ein Tool zur Erstellung von Anwendungen in Docker-Images entwickelten, merkten wir schnell, dass Dockerfile fĂŒr einige spezifische Aufgaben nicht geeignet war:
- Die Notwendigkeit, typische kleine Webanwendungen nach folgendem Standard-Schema zu erstellen:
- SystemabhÀngigkeiten der Anwendung zu installieren,
- BĂŒndel von AbhĂ€ngigkeiten der Anwendung zu installieren,
- Assets zu sammeln,
- und das Wichtigste â den Code im Image schnell und effizient zu aktualisieren.
- Bei Ănderungen in den Projektdateien muss der Builder schnell eine neue Schicht erstellen, indem er einen Patch auf die geĂ€nderten Dateien anwendet.
- Wenn bestimmte Dateien geÀndert werden, muss die entsprechende abhÀngige Phase neu erstellt werden.
Heute bietet unser Builder viele weitere Funktionen, aber die ursprĂŒnglichen WĂŒnsche und Impulse waren so.
Insgesamt haben wir kurzerhand die verwendete Programmiersprache gewĂ€hlt (siehe unten) und sind losgezogen â um umzusetzen unseren eigenen DSL! Entsprechend den Anforderungen war es vorgesehen, den Prozess der schrittweisen Erstellung und die AbhĂ€ngigkeiten dieser Phasen von Dateien zu beschreiben. ErgĂ€nzt wurde es durch unseren eigenen Builder, der DSL in das Endziel â das erstellte Image â umwandelte. ZunĂ€chst war DSL in Ruby, und im Zuge des wurde die Konfiguration unseres Builders in einer YAML-Datei beschrieben.

Alterer Konfigurationsdatei fĂŒr dapp in Ruby

Aktuelle Konfigurationsdatei fĂŒr werf in YAML
Der Arbeitsmechanismus des Builders hat sich im Laufe der Zeit ebenfalls verĂ€ndert. ZunĂ€chst haben wir einfach eine temporĂ€re Dockerfile aus unserer Konfiguration zur Laufzeit generiert. AnschlieĂend begannen wir, Buildanweisungen in temporĂ€ren Containern auszufĂŒhren und sie zu committen.
NB: Derzeit ist unser Builder, der mit seiner Konfiguration (in YAML) arbeitet und Stapel-Builder genannt wird, zu einem leistungsstarken Werkzeug gereift. Eine ausfĂŒhrliche Beschreibung verdient eigene Artikel, wĂ€hrend die wichtigsten Details aus .
Das Bewusstsein fĂŒr das Problem
Aber wir haben, was nicht sofort klar wurde, einen Fehler gemacht: Wir haben die Möglichkeit nicht hinzugefĂŒgt, Images ĂŒber die Standard-Dockerfile zu bauen und sie in die gleiche Infrastruktur des umfassenden Anwendungsmanagements zu integrieren (d.h. Images zu bauen, sie zu deployen und sie zu bereinigen). Wie konnte man ein Deployment-Tool fĂŒr Kubernetes entwickeln und dabei den Support fĂŒr Dockerfile, das heiĂt die standardisierte Art der Beschreibung von Images fĂŒr die meisten Projekte, nicht implementieren?
Anstatt auf diese Frage zu antworten, bieten wir eine Lösung. Was tun, wenn Sie bereits ein Dockerfile (oder eine Reihe von Dockerfiles) haben und werf verwenden möchten?
NB: Ăbrigens, warum sollten Sie ĂŒberhaupt werf verwenden wollen? Die Hauptmerkmale lassen sich wie folgt zusammenfassen:
- vollstĂ€ndiger Lebenszyklus des Anwendungsmanagements einschlieĂlich der Bereinigung von Images;
- Möglichkeit, den Build mehrerer Images aus einer einzigen Konfiguration zu steuern;
- verbesserten Deployment-Prozess fĂŒr Helm-kompatible Charts.
Eine vollstÀndige Liste der Funktionen finden Sie auf .
Also, wenn wir frĂŒher vorgeschlagen hĂ€tten, das Dockerfile in unsere Konfiguration umzuschreiben, sagen wir jetzt gerne: âLassen Sie werf Ihre Dockerfiles bauen!â
Wie verwendet man das?
Die vollstĂ€ndige Implementierung dieses Features wurde in der Version . Das Grundprinzip ist einfach: Der Benutzer gibt den Pfad zur bestehenden Dockerfile in der werf-Konfiguration an und fĂŒhrt dann den Befehl aus werf build⊠und das war's â werf wird das Image bauen. Lassen Sie uns ein abstraktes Beispiel betrachten.
Lassen Sie uns den nÀchsten Dockerfile im Stammverzeichnis des Projekts deklarieren:
FROM ubuntu:18.04
RUN echo Bau ... Und erklÀren wir werf.yaml, der dieses nutzt Dockerfile:
configVersion: 1
project: dockerfile-example
---
image: ~
dockerfile: .\/Dockerfile Das ist alles! Jetzt bleibt es gestart werden werf build:

DarĂŒber hinaus kann der nĂ€chste werf.yaml fĂŒr den gleichzeitigen Bau mehrerer Images aus verschiedenen Dockerfiles deklariert werden:
configVersion: 1
project: dockerfile-example
---
image: backend
dockerfile: .\/dockerfiles\/Dockerfile-backend
---
image: frontend
dockerfile: .\/dockerfiles\/Dockerfile-frontend Endlich wird auch die Ăbertragung zusĂ€tzlicher Build-Parameter unterstĂŒtzt, wie z. B. --build-arg und --add-host â ĂŒber die werf-Konfiguration. Eine vollstĂ€ndige Beschreibung der Dockerfile-Image-Konfiguration ist verfĂŒgbar auf .
Wie funktioniert das?
WĂ€hrend des Build-Vorgangs funktioniert der Standard-Cache der lokalen Schichten in Docker. Wichtig ist jedoch, dass werf auch die Dockerfile-Konfiguration in seine Infrastruktur integriert.. Was bedeutet das?
- Jedes Image, das aus einem Dockerfile erstellt wird, besteht aus einer Phase, die genannt wird
dockerfile(weiterfĂŒhrende Informationen zu Phasen in werf können gelesen werden ). - FĂŒr die Phase
dockerfileberechnet werf eine Signatur, die von dem Inhalt der Dockerfile-Konfiguration abhÀngt. Wenn die Dockerfile-Konfiguration geÀndert wird, Àndert sich die Signatur der Phasedockerfileund werf initiiert die Neubau dieser Phase mit der neuen Dockerfile-Konfiguration. Wenn sich die Signatur jedoch nicht Àndert, verwendet werf das Image aus dem Cache (nÀhere Informationen zur Verwendung von Signaturen in werf wurden in ). - Die erstellten Images können dann mit dem Befehl
werf publish(oderwerf build-and-publish) veröffentlicht und zur Bereitstellung in Kubernetes verwendet werden. Die veröffentlichten Images im Docker-Registry werden mit den Standardbereinigungsmethoden von werf bereinigt, das heiĂt, es erfolgt eine automatische Bereinigung alter Images (Ă€lter als N Tage), von Images, die mit nicht existierenden Git-Zweigen verbunden sind, und gemÀà anderen Richtlinien.
Weitere Informationen zu den hier beschriebenen Punkten finden Sie in der Dokumentation:
- ;
- ;
- .
Anmerkungen und VorsichtsmaĂnahmen
1. Externe URLs in ADD werden nicht unterstĂŒtzt
Derzeit wird die Verwendung externer URLs in der Direktive ADD. Werf wird bei einer Ănderung der Ressource unter der angegebenen URL keine Neubau initiieren. Diese Funktion wird in naher Zukunft hinzugefĂŒgt.
2. .git darf nicht in das Image hinzugefĂŒgt werden
Im Allgemeinen ist das HinzufĂŒgen des Verzeichnisses .git zum Image eine schlechte Praxis, und das sind die GrĂŒnde:
- Wenn
.gitbleibt im finalen Image, was die Prinzipien von : da das finale Image mit einem Commit verknĂŒpft sein sollte, darf es keine Möglichkeit geben, einengit checkoutwillkĂŒrlichen Commit zu machen. -
.giterhöht die GröĂe des Images (das Repository könnte groĂ sein, weil irgendwann groĂe Dateien hinzugefĂŒgt wurden und spĂ€ter gelöscht wurden). Die GröĂe des Arbeitsbaums, der nur mit einem bestimmten Commit verbunden ist, hĂ€ngt nicht von der Historie der Operationen in Git ab. Dabei fĂŒhrt das HinzufĂŒgen und anschlieĂende Löschen.gitDas finale Image wird nicht funktionieren: Das Image wird dennoch eine zusĂ€tzliche Schicht erhalten â so funktioniert Docker. - Docker kann eine unnötige Neuaufbau-Aktion initiieren, selbst wenn der gleiche Commit aus verschiedenen Work-Trees gebaut wird. Zum Beispiel erstellt GitLab separate geklonte Verzeichnisse in
/home/gitlab-runner/builds/HASH/[0-N]/yourprojectaktiviertem Parallelaufbau. Die unnötige Neuaufbau-Aktion wird damit zusammenhÀngen, dass das Verzeichnis.gitin den verschiedenen geklonnten Versionen des gleichen Repositories unterschiedlich ist, auch wenn derselbe Commit gebaut wird.
Der letzte Punkt hat auch eine Konsequenz bei der Verwendung von werf. Werf erfordert, dass der gebaute Cache bei der AusfĂŒhrung bestimmter Befehle vorhanden ist (z. B. werf deploy). WĂ€hrend der AusfĂŒhrung solcher Befehle berechnet werf die Signaturen der Stufen fĂŒr die angegebenen Images, werf.yaml, und diese mĂŒssen sich im Build-Cache befinden â andernfalls kann der Befehl nicht fortgesetzt werden. Wenn jedoch die Signatur der Stufen von den Inhalten .gitabhĂ€ngt, erhalten wir einen instabilen Cache, der nicht gegen Ănderungen in irrelevanten Dateien resistent ist, und werf kann einen solchen Fehler nicht verzeihen (siehe dazu ).
Im Allgemeinen das HinzufĂŒgen nur bestimmter notwendiger Dateien ĂŒber die Anweisung ADD in jedem Fall erhöht die Effizienz und ZuverlĂ€ssigkeit des Geschriebenen Dockerfile, sowie die Resistenz des in Bezug auf das Build-Cache gegen irrelevante Ănderungen in Git. DockerfileUnser ursprĂŒnglicher Weg, einen eigenen Builder fĂŒr spezifische BedĂŒrfnisse zu schreiben, war mĂŒhsam, ehrlich und geradlinig: Anstatt Notlösungen ĂŒber dem Standard-Dockerfile zu verwenden, haben wir unsere eigene Lösung mit benutzerdefinierter Syntax geschrieben. Und das brachte seine Vorteile: Der Stapel-Builder erfĂŒllt seine Aufgabe hervorragend.
Fazit
Allerdings haben wir bei der Erstellung unseres eigenen Builders die UnterstĂŒtzung bereits vorhandener Dockerfiles auĂer Acht gelassen. Dieser Mangel ist jetzt behoben, und in Zukunft planen wir, die UnterstĂŒtzung von Dockerfiles parallel zu unserem benutzerdefinierten Stapel-Builder fĂŒr verteilte Builds und fĂŒr Builds mit Kubernetes weiterzuentwickeln (d. h. Builds auf Runnern innerhalb von Kubernetes, wie es in kaniko gemacht wird).
Also, falls Sie zufÀllig ein paar Dockerfiles herumliegen haben...
P.S. Eine Liste von Dokumentationen zu diesem Thema versuchen Sie es !
LeitfĂ€den fĂŒr einen schnellen Einstieg
- ;
- ;
- ;
- ;
- ;
- ;
- .
Besser spÀt als nie.».
Quelle: habr.com
