{"id":32526,"date":"2019-10-31T21:47:32","date_gmt":"2019-10-31T18:47:32","guid":{"rendered":"https:\/\/prohoster.info\/blog\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci\/"},"modified":"2019-10-31T21:47:32","modified_gmt":"2019-10-31T18:47:32","slug":"protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","status":"publish","type":"post","link":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","title":{"rendered":"Der Entwicklungs- und Testprozess mit Docker und GitLab CI","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><strong>Ich lade Sie ein, sich mit der Zusammenfassung des Berichts von Alexander Sigachev von Inventos \"Entwicklungs- und Testprozess mit Docker + Gitlab CI\" vertraut zu machen.<\/strong><\/p>\n<p><\/p>\n<p>Diejenigen, die gerade erst beginnen, den Entwicklungs- und Testprozess auf Basis von Docker + GitLab CI einzuf\u00fchren, stellen h\u00e4ufig grundlegende Fragen. Wo fange ich an? Wie organisiere ich das? Wie teste ich es?<\/p>\n<p><\/p>\n<p>Dieser Vortrag ist besonders, da er strukturiert \u00fcber den Entwicklungs- und Testprozess unter Verwendung von Docker und GitLab CI berichtet. Der Vortrag stammt aus dem Jahr 2017. Ich denke, dass man aus diesem Vortrag Grundlagen, Methoden, Ideen und Erfahrungen sammeln kann. <\/p>\n<p>\n<center><div class=\"youtube-placeholder\" data-id=\"lJsqRwULRVA\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/lJsqRwULRVA\/hqdefault.jpg\" alt=\"Video abspielen\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><\/p>\n<p>Wer interessiert ist, ist herzlich eingeladen, weiterzulesen. <noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><\/p>\n<p>Mein Name ist Alexander Sigachev. Ich arbeite bei Inventos. Ich werde von meinen Erfahrungen mit Docker berichten und wie wir es schrittweise in unsere Projekte im Unternehmen integrieren.<\/p>\n<p><\/p>\n<p>Thema des Vortrags: Entwicklungsprozess mit Docker und GitLab CI. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/e30c4757e4bda1bcc3e20b16e8e2709e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Das ist mein zweiter Vortrag \u00fcber Docker. Zum Zeitpunkt des ersten Vortrags nutzten wir Docker nur in der Entwicklungsphase auf den Maschinen der Entwickler. Die Anzahl der Mitarbeiter, die Docker verwendeten, lag bei etwa 2-3 Personen. Nach und nach haben wir Erfahrungen gesammelt und sind ein St\u00fcck weitergekommen. Link zu unserem <noindex><a rel=\"nofollow\" href=\"https:\/\/www.slideshare.net\/gled\/docker-development-70411088\">erster Bericht<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Was wird in diesem Bericht behandelt? Wir teilen unsere Erfahrungen dar\u00fcber, welche Stolpersteine wir gesammelt haben und wie wir Probleme gel\u00f6st haben. Es war nicht immer einfach, aber es hat uns erm\u00f6glicht, weiter voranzukommen.<\/p>\n<p><\/p>\n<p>Unser Motto: Docker alles, was in unsere H\u00e4nde kommt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/25ae4f97f1c502384abfe697bac502b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Welche Probleme l\u00f6sen wir?<\/p>\n<p><\/p>\n<p>Wenn in einem Unternehmen mehrere Teams existieren, ist der Programmierer eine gefragte Ressource. Es gibt Phasen, in denen Programmierer aus einem Projekt herausgezogen und f\u00fcr eine gewisse Zeit in ein anderes Projekt gegeben werden.<\/p>\n<p><\/p>\n<p>Damit ein Programmierer schnell einsteigen kann, muss er den Quellcode des Projekts herunterladen und so schnell wie m\u00f6glich eine Umgebung starten, die es ihm erm\u00f6glicht, die Aufgaben dieses Projekts zu l\u00f6sen.<\/p>\n<p><\/p>\n<p>Normalerweise gibt es, wenn man von Grund auf neu anf\u00e4ngt, wenig Dokumentation im Projekt. Die Informationen zur Einrichtung haben nur die alten Hasen. Die Mitarbeiter richten ihren Arbeitsplatz normalerweise in ein oder zwei Tagen selbst ein. Um diesen Prozess zu beschleunigen, haben wir Docker verwendet.<\/p>\n<p><\/p>\n<p>Ein weiterer Grund sind die Standardisierungen der Einstellungen in der Entwicklung. Meiner Erfahrung nach zeigen Entwickler immer Initiative. In jedem f\u00fcnften Fall wird eine benutzerdefinierte Domain wie vasya.dev eingef\u00fchrt. Daneben sitzt Nachbar Petja, der die Domain petya.dev hat. Sie entwickeln eine Website oder ein Systemkomponente unter Verwendung dieses Domainnamens.<\/p>\n<p><\/p>\n<p>Wenn das System gr\u00f6\u00dfer wird und diese Domainnamen in die Konfigurationen gelangen, entstehen Konflikte zwischen den Entwicklungsumgebungen und der Pfad der Website wird \u00fcberschrieben.<\/p>\n<p><\/p>\n<p>Das Gleiche passiert mit den Datenbankeinstellungen. Manche k\u00fcmmern sich nicht um die Sicherheit und arbeiten mit einem leeren root-Passwort. Bei anderen wurde w\u00e4hrend der MySQL-Installation ein Passwort gefordert und das Passwort war einfach 123. Es kommt h\u00e4ufig vor, dass die Datenbankkonfiguration st\u00e4ndig je nach Commit des Entwicklers ge\u00e4ndert wurde. Jemand hat die Konfiguration angepasst, jemand anderer nicht. Es gab Tricks, bei denen wir eine Art Testkonfiguration ins <code>.gitignore<\/code> Jeder Entwickler muss eine Datenbank einrichten, was den Startprozess kompliziert. Man darf nicht vergessen, dass auch die Datenbank ber\u00fccksichtigt werden muss. Sie muss initialisiert, das Passwort eingegeben, ein Benutzer angelegt und eine Tabelle erstellt werden, und so weiter.<\/p>\n<p><\/p>\n<p>Ein weiteres Problem sind die unterschiedlichen Versionen der Bibliotheken. H\u00e4ufig arbeitet ein Entwickler an verschiedenen Projekten. Es gibt ein Legacy-Projekt, das vor f\u00fcnf Jahren (seit 2017 \u2013 Anm. d. Red.) begonnen wurde und mit MySQL 5.5 gestartet ist. Daneben gibt es moderne Projekte, in denen wir versuchen, bereits aktuellere Versionen von MySQL einzuf\u00fchren, etwa 5.7 oder h\u00f6her (im Jahr 2017 \u2013 Anm. d. Red.).<\/p>\n<p><\/p>\n<p>Wer mit MySQL arbeitet, wei\u00df, dass diese Bibliotheken Abh\u00e4ngigkeiten mit sich bringen. Es ist ziemlich problematisch, zwei Datenbanken gleichzeitig zu betreiben. Zumindest ist es schwierig, \u00e4ltere Clients mit einer neuen Datenbank zu verbinden. Dies f\u00fchrt seinerseits zu mehreren Problemen.<\/p>\n<p><\/p>\n<p>Das n\u00e4chste Problem ist, dass der Entwickler auf seiner lokalen Maschine arbeitet, wobei er lokale Ressourcen, lokale Dateien und lokalen RAM verwendet. Alle Interaktionen w\u00e4hrend der Entwicklung der L\u00f6sungen finden innerhalb der Rahmenbedingungen statt, dass alles auf einer Maschine funktioniert. Ein Beispiel ist, wenn wir in der Produktion drei Backend-Server haben und der Entwickler Dateien im Stammverzeichnis speichert, von dem aus Nginx die Dateien zur Beantwortung von Anfragen abruft. Wenn solcher Code in die Produktion gelangt, ist die Datei nur auf einem der drei Server vorhanden.<\/p>\n<p><\/p>\n<p>Derzeit entwickelt sich der Bereich der Microservices. Wenn wir unsere gro\u00dfen Anwendungen in kleinere, miteinander kommunizierende Komponenten aufteilen. Dies erm\u00f6glicht es, f\u00fcr spezifische Aufgaben den passenden Technologie-Stack auszuw\u00e4hlen. Au\u00dferdem erlaubt es, die Arbeit und Verantwortlichkeiten zwischen den Entwicklern aufzuteilen.<\/p>\n<p><\/p>\n<p>Der Frontend-Entwickler, der mit JS arbeitet, hat kaum Einfluss auf das Backend. Der Backend-Entwickler hingegen entwickelt in unserem Fall mit Ruby on Rails, was das Frontend nicht beeintr\u00e4chtigt. Die Interaktion erfolgt \u00fcber APIs.<\/p>\n<p><\/p>\n<p>Als Bonus konnten wir mit Docker die Ressourcen in der Staging-Umgebung optimieren. Jedes Projekt erforderte aufgrund seiner Spezifit\u00e4t bestimmte Einstellungen. Physisch mussten entweder separate virtuelle Server bereitgestellt und individuell konfiguriert werden oder wir mussten eine variable Umgebung teilen, was dazu f\u00fchrte, dass die Projekte je nach Version der Bibliotheken Einfluss aufeinander hatten.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/fa5c99f90faef84a356d4791fd915830.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Werkzeuge. Was verwenden wir? <\/p>\n<p><\/p>\n<ul>\n<li>Direkt Docker selbst. Im Dockerfile werden die Abh\u00e4ngigkeiten einer Anwendung beschrieben. <\/li>\n<li>Docker-Compose ist das Bindeglied, das unsere verschiedenen Docker-Anwendungen vereint.<\/li>\n<li>GitLab verwenden wir zur Speicherung des Quellcodes.<\/li>\n<li>GitLab-CI nutzen wir f\u00fcr die systematische Integration.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/b6041827a6ba928e0d33add6b79c581c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Der Bericht besteht aus zwei Teilen.<\/p>\n<p><\/p>\n<p>Der erste Teil erl\u00e4utert, wie wir Docker auf den Maschinen der Entwickler gestartet haben.<\/p>\n<p><\/p>\n<p>Der zweite Teil beschreibt, wie wir mit GitLab interagieren, wie wir Tests starten und wie wir auf Staging deployen.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/45746d3323d35e0d18f066c8bfcb2214.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Docker \u2014 dies ist eine Technologie, die es erm\u00f6glicht, erforderliche Komponenten mithilfe eines deklarativen Ansatzes zu beschreiben. Hier sehen wir ein Beispiel f\u00fcr ein Dockerfile. Wir erkl\u00e4ren, dass wir von dem offiziellen Docker-Image Ruby:2.3.0 erben. Es enth\u00e4lt die installierte Ruby-Version 2.3. Wir installieren die erforderlichen Build-Bibliotheken sowie NodeJS. Zudem beschreiben wir, dass wir ein Verzeichnis erstellen. <code>\/app<\/code>Wir setzen das Verzeichnis app als Arbeitsverzeichnis. In dieses Verzeichnis legen wir die notwendigen minimalen Dateien Gemfile und Gemfile.lock. Anschlie\u00dfend f\u00fchren wir den Build von Projekten durch, die die Abh\u00e4ngigkeiten f\u00fcr dieses Image installieren. Wir geben an, dass der Container bereit sein wird, auf dem externen Port 3000 zuzuh\u00f6ren. Der letzte Befehl ist der Befehl, der unsere Anwendung tats\u00e4chlich startet. Wenn wir das Projektstartkommando ausf\u00fchren, versucht die Anwendung, sich auszuf\u00fchren und den angegebenen Befehl zu starten.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/ba503c305ae90f49b39f4ae2cbda1668.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dies ist ein einfaches Beispiel f\u00fcr eine Docker-Compose-Datei. In diesem Fall zeigen wir, wie zwei Container miteinander verbunden sind. Dies betrifft direkt den Datenbankservice und den Webservice. Unsere Webanwendungen ben\u00f6tigen in den meisten F\u00e4llen eine Datenbank als Backend zur Speicherung von Daten. Da wir MySQL verwenden, ist dies ein Beispiel mit MySQL \u2013 aber es steht nichts im Wege, eine andere Datenbank wie PostgreSQL oder Redis zu nutzen.<\/p>\n<p><\/p>\n<p>Wir nehmen das offizielle Image MySQL 5.7.14 ohne \u00c4nderungen von Docker Hub. Das Image, das f\u00fcr unsere Webanwendung verantwortlich ist, erstellen wir aus dem aktuellen Verzeichnis. Es wird w\u00e4hrend des ersten Starts f\u00fcr uns gebaut. Danach wird der Befehl ausgef\u00fchrt, den wir hier angeben. Wenn wir zur\u00fcckblicken, sehen wir, dass der Startbefehl \u00fcber Puma definiert wurde. Puma ist ein Service, der in Ruby geschrieben wurde. Im zweiten Fall \u00fcberschreiben wir diesen Befehl. Dieser kann abh\u00e4ngig von unseren Bed\u00fcrfnissen oder Aufgaben beliebig sein.<\/p>\n<p><\/p>\n<p>Au\u00dferdem beschreiben wir, dass der Port auf unserer Host-Maschine vom Entwickler von 3000 auf den Containerport 3000 weitergeleitet werden muss. Dies geschieht automatisch mithilfe von iptables und dem integrierten Mechanismus von Docker. <\/p>\n<p><\/p>\n<p>Der Entwickler kann wie zuvor auf jede verf\u00fcgbare IP-Adresse zugreifen, beispielsweise auf die lokale 127.0.0.1 oder die externe IP-Adresse des Servers.<\/p>\n<p><\/p>\n<p>Die letzte Zeile besagt, dass der Web-Container von dem DB-Container abh\u00e4ngt. Wenn wir den Web-Container starten, wird Docker Compose zuerst die Datenbank starten. Nach dem Start der Datenbank (beziehungsweise nach dem Start des Containers! Die Bereitschaft der DB ist damit nicht garantiert) wird unsere Anwendung, unser Backend, gestartet.<\/p>\n<p><\/p>\n<p>Dies hilft, Fehler zu vermeiden, wenn die Datenbank nicht l\u00e4uft, und spart Ressourcen, wenn wir den Datenbankcontainer stoppen, wodurch Ressourcen f\u00fcr andere Projekte frei werden. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4acbcf5de89b98db055e8abc419202de.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Was uns die Verwendung von Docker f\u00fcr die Datenbank im Projekt bringt. Wir fixieren f\u00fcr alle Entwickler die MySQL-Version. Dies hilft, gewisse Fehler zu vermeiden, die durch abweichende Versionen entstehen k\u00f6nnen, wenn sich die Syntax, Konfiguration oder Standardwerte \u00e4ndern. Es erm\u00f6glicht uns, gemeinsame Hostnamen f\u00fcr die Datenbank, Login und Passwort anzugeben. Dadurch vermeiden wir die Verwirrung und Konflikte bei den Konfigurationsdateien, die zuvor entstanden sind. <\/p>\n<p><\/p>\n<p>Wir haben die M\u00f6glichkeit, eine optimierte Konfiguration f\u00fcr die Entwicklungsumgebung zu verwenden, die sich vom Standard unterscheidet. MySQL ist standardm\u00e4\u00dfig f\u00fcr schwache Maschinen konfiguriert und seine Leistung ist direkt nach der Installation sehr gering.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/417d77a06b18e2df9b71440c0f2a1653.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Docker erm\u00f6glicht die Nutzung der gew\u00fcnschten Version von Python, Ruby, NodeJS oder PHP. Dadurch entf\u00e4llt die Notwendigkeit, einen Versionsmanager zu verwenden. Fr\u00fcher haben wir f\u00fcr Ruby ein rpm-Paket verwendet, das es erlaubte, die Version je nach Projekt zu \u00e4ndern. Au\u00dferdem erm\u00f6glicht es uns, dank des Docker-Containers den Code reibungslos zu migrieren und zusammen mit seinen Abh\u00e4ngigkeiten versionieren. Wir haben daher kein Problem, die Version sowohl des Interpreters als auch des Codes zu verstehen. Um die Version zu aktualisieren, m\u00fcssen wir den alten Container l\u00f6schen und den neuen Container starten. Wenn etwas schiefgeht, k\u00f6nnen wir den neuen Container l\u00f6schen und den alten Container wiederherstellen.<\/p>\n<p><\/p>\n<p>Nach dem Erstellen des Abbilds werden die Container sowohl in der Entwicklungs- als auch in der Produktionsumgebung identisch sein. Dies ist besonders wichtig f\u00fcr gro\u00dfe Installationen.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/185a1bfe257f7e3e0eecdc6e0e0d330f.jpg\" style=\"display:block;margin: 0 auto;\" \/> Im Frontend verwenden wir JavaScript und NodeJS.<\/p>\n<p><\/p>\n<p>Das aktuelle Projekt basiert auf ReactJS. Der Entwickler hat alle Container gestartet und arbeitete mit Hot-Reload.<\/p>\n<p><\/p>\n<p>Im n\u00e4chsten Schritt wird die Aufgabe zum Zusammenstellen von JavaScript gestartet, und der als statisch zusammengestellte Code wird \u00fcber Nginx bereitgestellt, um Ressourcen zu sparen.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4c2e28319d56d7fc81845b4133a1bfe6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hier ist das Schema unseres letzten Projekts.<\/p>\n<p><\/p>\n<p>Welche Herausforderungen haben wir gel\u00f6st? Wir mussten ein System aufbauen, das mit mobilen Ger\u00e4ten interagiert. Diese erhalten Daten. Eine der M\u00f6glichkeiten besteht darin, Push-Benachrichtigungen an dieses Ger\u00e4t zu senden. <\/p>\n<p><\/p>\n<p>Was haben wir daf\u00fcr getan?<\/p>\n<p><\/p>\n<p>Wir haben die Anwendung in folgende Komponenten unterteilt: das Admin-Panel in JS, das Backend, das \u00fcber ein REST-Interface unter Ruby on Rails arbeitet. Das Backend interagiert mit der Datenbank. Die Ergebnisse werden an den Client zur\u00fcckgegeben. Das Admin-Panel kommuniziert mit dem Backend und der Datenbank \u00fcber das REST-Interface.<\/p>\n<p><\/p>\n<p>Au\u00dferdem hatten wir die Notwendigkeit, Push-Benachrichtigungen zu versenden. Zuvor hatten wir ein Projekt, in dem ein Mechanismus umgesetzt wurde, der f\u00fcr die Zustellung von Benachrichtigungen auf mobilen Plattformen verantwortlich ist. <\/p>\n<p><\/p>\n<p>Wir haben folgendes Schema entwickelt: Der Operator im Browser interagiert mit dem Admin-Panel, das Admin-Panel interagiert mit dem Backend, und es wird die Aufgabe gesetzt, Push-Benachrichtigungen zu senden.<\/p>\n<p><\/p>\n<p>Push-Benachrichtigungen interagieren mit einer anderen Komponente, die auf NodeJS implementiert ist.<\/p>\n<p><\/p>\n<p>Warteschlangen werden aufgebaut und die Benachrichtigungen werden entsprechend ihrem Mechanismus weiter gesendet.<\/p>\n<p><\/p>\n<p>Hier sind zwei Datenbanken dargestellt. Aktuell nutzen wir mithilfe von Docker zwei unabh\u00e4ngige Datenbanken, die nicht miteinander verbunden sind. Abgesehen von ihrem gemeinsamen virtuellen Netzwerk werden die physischen Daten in verschiedenen Verzeichnissen auf dem Entwicklungsrechner gespeichert.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/dfde59db7e6886d2d851dcf884049318.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Das Gleiche, aber in Zahlen. Hier ist die Wiederverwendung von Code wichtig.<\/p>\n<p><\/p>\n<p>Wenn wir zuvor \u00fcber die Wiederverwendung von Code in Form von Bibliotheken gesprochen haben, wird in diesem Beispiel unser Service f\u00fcr Push-Benachrichtigungen als vollst\u00e4ndiger Server wiederverwendet. Er stellt eine API zur Verf\u00fcgung, mit der unsere neue Entwicklung interagiert.<\/p>\n<p><\/p>\n<p>Zu diesem Zeitpunkt verwendeten wir NodeJS Version 4. Jetzt (im Jahr 2017 \u2013 Anmerkung des Herausgebers) verwenden wir in neuen Entwicklungen Version 7 von NodeJS. Es gibt keine Probleme, in neuen Komponenten neue Bibliotheksversionen einzubinden. <\/p>\n<p><\/p>\n<p>Falls n\u00f6tig, kann ein Refactoring durchgef\u00fchrt und die NodeJS-Version im Push-Benachrichtigungsdienst aktualisiert werden. <\/p>\n<p><\/p>\n<p>Wenn wir die API-Kompatibilit\u00e4t gew\u00e4hrleisten k\u00f6nnen, w\u00e4re es m\u00f6glich, ihn in anderen Projekten zu ersetzen, die zuvor verwendet wurden.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/5c58c65be078a5a1b9fc17ee2e7b4ad4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Was ben\u00f6tigt man, um Docker hinzuzuf\u00fcgen? Wir f\u00fcgen unseren Docker-Repository eine Dockerfile hinzu, die die notwendigen Abh\u00e4ngigkeiten beschreibt. In diesem Beispiel sind die Komponenten nach Logik aufgeteilt. Dies ist das Minimalset f\u00fcr einen Backend-Entwickler.<\/p>\n<p><\/p>\n<p>Beim Erstellen eines neuen Projekts erstellen wir eine Dockerfile und beschreiben das ben\u00f6tigte \u00d6kosystem (Python, Ruby, NodeJS). In docker-compose wird die n\u00f6tige Abh\u00e4ngigkeit \u2014 die Datenbank \u2014 beschrieben. Wir geben an, dass eine Datenbank dieser Version erforderlich ist, um Daten dort zu speichern.<\/p>\n<p><\/p>\n<p>Wir nutzen einen separaten dritten Container mit nginx, um statische Inhalte zu bedienen. Es besteht die M\u00f6glichkeit, Bilder hochzuladen. Der Backend-Server speichert diese in einem bereits vorbereiteten Volume, welches ebenfalls in den Container mit nginx eingebunden ist, der die statischen Inhalte bereitstellt.<\/p>\n<p><\/p>\n<p>Um die Konfiguration von nginx und MySQL zu speichern, haben wir einen Docker-Ordner hinzugef\u00fcgt, in dem wir die notwendigen Konfigurationen aufbewahren. Wenn ein Entwickler das Repository mit git klont, erh\u00e4lt er bereits ein Projekt, das f\u00fcr die lokale Entwicklung bereit ist. Es stellt sich nicht die Frage, welcher Port oder welche Einstellungen anzuwenden sind.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/e7a6b308a75cacf8ce60687a9e6081dd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dar\u00fcber hinaus haben wir mehrere Komponenten: Admin, Info-API, Push-Benachrichtigungen.<\/p>\n<p><\/p>\n<p>Um das Ganze zum Laufen zu bringen, haben wir ein weiteres Repository erstellt, das wir dockerized-app genannt haben. Momentan nutzen wir mehrere Repositories f\u00fcr jede Komponente. Diese unterscheiden sich lediglich logisch \u2014 in GitLab sieht das aus wie ein Ordner, w\u00e4hrend es auf dem Rechner des Entwicklers als Ordner f\u00fcr ein spezielles Projekt erscheint. Eine Stufe darunter liegen die Komponenten, die kombiniert werden.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/f4e2c45c8ec20fca0bac74b3a3892543.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Das ist ein Beispiel f\u00fcr den Inhalt von dockerized-app. Hier bringen wir auch das Docker-Verzeichnis unter, in dem wir die Konfigurationen bereitstellen, die f\u00fcr das Zusammenspiel aller Komponenten erforderlich sind. Es gibt eine README.md, in der kurz erkl\u00e4rt wird, wie man das Projekt startet.<\/p>\n<p><\/p>\n<p>Hier haben wir zwei docker-compose-Dateien eingesetzt. Das wurde gemacht, um die M\u00f6glichkeit zu haben, schrittweise zu starten. Wenn der Entwickler mit dem Kern arbeitet und keine Push-Benachrichtigungen ben\u00f6tigt, startet er einfach die docker-compose-Datei, wodurch Ressourcen gespart werden.<\/p>\n<p><\/p>\n<p>Bei Bedarf einer Integration mit Push-Benachrichtigungen wird die docker-compose.yaml und die docker-compose-push.yaml gestartet.<\/p>\n<p><\/p>\n<p>Da docker-compose.yaml und docker-compose-push.yaml im Ordner liegen, wird automatisch ein einheitliches virtuelles Netzwerk erstellt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/535019c82c72c1602176fbaf4aa5640f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Beschreibung der Komponenten. Dies ist eine ausf\u00fchrlichere Datei, die f\u00fcr das Zusammenstellen von Komponenten verantwortlich ist. Was ist hier bemerkenswert? Hier f\u00fchren wir den Load-Balancer-Komponenten ein.<\/p>\n<p><\/p>\n<p>Dies ist ein fertiges Docker-Image, in dem Nginx und eine Anwendung ausgef\u00fchrt werden, die den Docker-Socket \u00fcberwacht. Dynamisch wird die Nginx-Konfiguration bei Ein- und Ausschalten der Container neu generiert. Der Umgang mit den Komponenten wird \u00fcber Subdomain-Namen verteilt.<\/p>\n<p><\/p>\n<p>F\u00fcr die Entwicklungsumgebung verwenden wir die Domain .dev \u2014 api.informer.dev. Anwendungen mit der Domain .dev sind auf der lokalen Maschine des Entwicklers verf\u00fcgbar.<\/p>\n<p><\/p>\n<p>Danach werden die Konfigurationen an jedes Projekt \u00fcbergeben und alle Projekte werden gleichzeitig gestartet.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/bc1e11e6f1fd1c837d2c8087d04145c4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Grafisch dargestellt, ist der Client unser Browser oder ein anderes Tool, mit dem wir Anfragen an den Load-Balancer stellen.<\/p>\n<p><\/p>\n<p>Der Load-Balancer bestimmt anhand des Domainnamens, auf welchen Container zugegriffen werden muss.<\/p>\n<p><\/p>\n<p>Das kann Nginx sein, das die JS-Admin-Oberfl\u00e4che bereitstellt. Es kann Nginx sein, das API oder statische Dateien bereitstellt, die von Nginx zum Hochladen von Bildern ausgeliefert werden.<\/p>\n<p><\/p>\n<p>Im Diagramm ist zu sehen, dass die Container in einem virtuellen Netzwerk verbunden sind und hinter einem Proxy versteckt werden.<\/p>\n<p><\/p>\n<p>Auf dem Entwicklerrechner kann man den Container \u00fcber die IP-Adresse ansprechen, aber wir wenden das grunds\u00e4tzlich nicht an. Ein direkter Zugriff ist nahezu nie erforderlich.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/2908c31fd9d3c79f6189bdbeeb6d028f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Welches Beispiel sollte man sich ansehen, um seine Anwendung zu dockerisieren? Meiner Meinung nach ist das offizielle Docker-Image f\u00fcr MySQL ein gutes Beispiel.<\/p>\n<p><\/p>\n<p>Es ist ziemlich komplex. Es gibt viele Versionen. Aber die Funktionalit\u00e4t deckt zahlreiche Anforderungen ab, die w\u00e4hrend der weiteren Entwicklung auftreten k\u00f6nnen. Wenn Sie sich die Zeit nehmen und verstehen, wie alles zusammenspielt, denke ich, dass Sie in der eigenst\u00e4ndigen Implementierung keine Probleme haben werden.<\/p>\n<p><\/p>\n<p>Auf hub.docker.com gibt es normalerweise Links zu github.com, wo die Rohdaten direkt zur Verf\u00fcgung stehen, aus denen Sie das Image selbst zusammenstellen k\u00f6nnen.<\/p>\n<p><\/p>\n<p>In diesem Repository gibt es au\u00dferdem das Skript docker-endpoint.sh, das f\u00fcr die initiale Einrichtung und die weitere Verarbeitung des Anwendungsstarts verantwortlich ist.<\/p>\n<p><\/p>\n<p>In diesem Beispiel besteht auch die M\u00f6glichkeit, Umgebungsvariablen zu konfigurieren. Durch die Definition von Umgebungsvariablen beim Start eines einzelnen Containers oder \u00fcber docker-compose k\u00f6nnen wir angeben, dass wir ein leeres Passwort f\u00fcr Docker f\u00fcr root in MySQL festlegen m\u00fcssen oder eines, das wir w\u00fcnschen.<\/p>\n<p><\/p>\n<p>Es besteht die M\u00f6glichkeit, ein zuf\u00e4lliges Passwort zu erstellen. Wir geben an, dass wir einen Benutzer ben\u00f6tigen, ein Passwort f\u00fcr den Benutzer festgelegt werden muss und eine Datenbank erstellt werden muss.<\/p>\n<p><\/p>\n<p>In unseren Projekten haben wir das Dockerfile, das f\u00fcr die Initialisierung zust\u00e4ndig ist, etwas vereinheitlicht. Dabei haben wir es auf unsere Bed\u00fcrfnisse angepasst, um einfach die Benutzerrechte zu erweitern, die von der Anwendung verwendet werden. Dies erm\u00f6glichte es uns, die Datenbank direkt \u00fcber die Konsolenanwendung zu erstellen. In Ruby-Anwendungen gibt es Befehle zum Erstellen, \u00c4ndern und L\u00f6schen von Datenbanken.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4a9b56e21819d28dd39753134d23fee4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dieses Beispiel zeigt, wie eine bestimmte Version von MySQL auf github.com aussieht. Das Dockerfile kann ge\u00f6ffnet werden, um zu sehen, wie dort die Installation abl\u00e4uft.<\/p>\n<p><\/p>\n<p>Das Skript docker-endpoint.sh dient als Einstiegspunkt. Bei der ersten Initialisierung sind einige Vorbereitungen erforderlich, die alle im Initialisierungsskript zusammengefasst sind.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4153fa46526f3d802931dd1db48b08cd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wir kommen zum zweiten Teil.<\/p>\n<p><\/p>\n<p>F\u00fcr die Speicherung des Quellcodes haben wir auf GitLab umgestellt. Dies ist ein leistungsstarkes System, das \u00fcber eine visuelle Benutzeroberfl\u00e4che verf\u00fcgt.<\/p>\n<p><\/p>\n<p>Ein Bestandteil von GitLab ist GitLab CI. Damit k\u00f6nnen wir Abl\u00e4ufe definieren, die sp\u00e4ter verwendet werden, um ein System zur Bereitstellung von Code oder zur Ausf\u00fchrung automatischer Tests zu organisieren.<\/p>\n<p><\/p>\n<p>Pr\u00e4sentation zu GitLab CI 2 <noindex><a rel=\"nofollow\" href=\"https:\/\/goo.gl\/uohKjI\">https:\/\/goo.gl\/uohKjI<\/a><\/noindex> \u2014 Pr\u00e4sentation vom Ruby Russia Club \u2014 sie ist recht detailliert und k\u00f6nnte f\u00fcr Sie von Interesse sein.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/5d26d20500f34eeb9768e6c3d91bbefa.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jetzt schauen wir uns an, was erforderlich ist, um GitLab CI zu aktivieren. Um GitLab CI zu starten, gen\u00fcgt es, eine Datei mit dem Namen .gitlab-ci.yml in das Stammverzeichnis des Projekts zu legen.<\/p>\n<p><\/p>\n<p>Hier beschreiben wir, was wir in einer Folge von Zust\u00e4nden wie Tests und Deployments ausf\u00fchren m\u00f6chten.<\/p>\n<p><\/p>\n<p>Wir f\u00fchren Skripte aus, die direkt den Docker-Compose-Bau unserer Anwendung aufrufen. Dies ist ein Beispiel f\u00fcr das Backend.<\/p>\n<p><\/p>\n<p>Anschlie\u00dfend geben wir an, dass die Migrationen zur \u00c4nderung der Datenbank durchgef\u00fchrt und die Tests ausgef\u00fchrt werden m\u00fcssen.<\/p>\n<p><\/p>\n<p>Wenn die Skripte korrekt ausgef\u00fchrt werden und keinen Fehlercode zur\u00fcckgeben, wechselt das System zur zweiten Phase des Deployments.<\/p>\n<p><\/p>\n<p>Die Deployment-Phase ist derzeit f\u00fcr staging implementiert. Wir haben keinen unterbrechungsfreien Neustart organisiert.<\/p>\n<p><\/p>\n<p>Wir beenden alle Container gezielt und starten dann alle Container neu, die in der ersten Phase w\u00e4hrend der Tests erstellt wurden.<\/p>\n<p><\/p>\n<p>Wir f\u00fchren Migrationen der Datenbanken f\u00fcr die aktuelle Umgebungsvariablen aus, die von den Entwicklern geschrieben wurden.<\/p>\n<p><\/p>\n<p>Es gibt einen Hinweis, dass dies nur f\u00fcr den Master-Branch angewendet werden sollte.<\/p>\n<p><\/p>\n<p>Bei \u00c4nderungen in anderen Branches wird dies nicht ausgef\u00fchrt.<\/p>\n<p><\/p>\n<p>Es besteht die M\u00f6glichkeit, Rollouts nach Branches zu organisieren.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/8a5b880bd9a0d4bab0b276568e2ba413.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Um dies weiter zu organisieren, m\u00fcssen wir den Gitlab Runner installieren.<\/p>\n<p><\/p>\n<p>Dieses Tool ist in Golang geschrieben. Es ist eine Einzeldatei, wie es in der Golang-Welt \u00fcblich ist, die keine Abh\u00e4ngigkeiten ben\u00f6tigt.<\/p>\n<p><\/p>\n<p>Bei der Ausf\u00fchrung registrieren wir den Gitlab Runner.<\/p>\n<p><\/p>\n<p>Wir erhalten den Schl\u00fcssel im Web-Interface von Gitlab.<\/p>\n<p><\/p>\n<p>Dann rufen wir den Initialisierungsbefehl in der Kommandozeile auf.<\/p>\n<p><\/p>\n<p>Wir konfigurieren den Gitlab Runner im Dialogmodus (Shell, Docker, VirtualBox, SSH).<\/p>\n<p><\/p>\n<p>Der Code auf dem Gitlab Runner wird bei jedem Commit ausgef\u00fchrt, abh\u00e4ngig von der Konfiguration in .gitlab-ci.yml.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/37c8ac7499f0cfba2eb07a84083e44e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>So sieht es visuell in GitLab im Web-Interface aus. Sobald wir GitLab CI verbunden haben, erscheint eine Flagge, die den aktuellen Status des Builds anzeigt.<\/p>\n<p><\/p>\n<p>Wir sehen, dass vor 4 Minuten ein Commit durchgef\u00fchrt wurde, der alle Tests bestanden hat und keine Probleme verursacht hat.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/33ac79c45f0651a5f8bde75092c4ac44.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wir k\u00f6nnen die Builds genauer betrachten. Hier sehen wir, dass bereits zwei Zust\u00e4nde durchlaufen wurden: der Testzustand und der Zustand des Deployments auf Staging.<\/p>\n<p><\/p>\n<p>Wenn wir auf einen bestimmten Build klicken, wird der Konsolenausgabe der Befehle angezeigt, die w\u00e4hrend des Prozesses gem\u00e4\u00df .gitlab-ci.yml ausgef\u00fchrt wurden.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/d26dd28708c7fc8a409af4be4d48f502.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>So sieht die Historie unseres Produkts aus. Wir sehen, dass erfolgreiche Versuche vorhanden sind. Wenn Tests fehlschlagen, wird der n\u00e4chste Schritt nicht ausgef\u00fchrt und der Code auf Staging wird nicht aktualisiert.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/ee7bd81dc283c7af0c194779d4230780.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Welche Herausforderungen hatten wir im Staging bei der Einf\u00fchrung von Docker? Unser System besteht aus Komponenten, und wir mussten die M\u00f6glichkeit schaffen, nur die Teile, die im Repository aktualisiert wurden, neu zu starten und nicht das gesamte System.<\/p>\n<p><\/p>\n<p>Daf\u00fcr mussten wir alles in separate Ordner aufteilen.<\/p>\n<p><\/p>\n<p>Nachdem wir das eingerichtet hatten, traten Probleme auf, da Docker-Compose f\u00fcr jeden Ordner sein eigenes Netzwerk erstellt und die Nachbarkomponenten nicht erkennt.<\/p>\n<p><\/p>\n<p>Um dies zu umgehen, haben wir manuell ein Netzwerk in Docker erstellt. In Docker-Compose haben wir festgelegt, dass dieses Projekt dieses Netzwerk nutzen soll.<\/p>\n<p><\/p>\n<p>Dadurch kann jede Komponente, die mit diesem Netzwerk gestartet wird, die Komponenten in anderen Teilen des Systems sehen.<\/p>\n<p><\/p>\n<p>Das n\u00e4chste Problem ist die Trennung von Staging zwischen mehreren Projekten.<\/p>\n<p><\/p>\n<p>Um das ansprechend und so nah wie m\u00f6glich an der Produktionsumgebung zu gestalten, ist es ratsam, die Ports 80 oder 443 zu verwenden, die \u00fcberall im Web genutzt werden.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/f863cf1833271bf132455a70ad7d2706.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wie haben wir das gel\u00f6st? Wir haben einen GitLab Runner f\u00fcr alle gr\u00f6\u00dferen Projekte zugewiesen.<\/p>\n<p><\/p>\n<p>GitLab erm\u00f6glicht das Starten mehrerer verteilten GitLab Runner, die einfach abwechselnd in zuf\u00e4lliger Reihenfolge alle Aufgaben \u00fcbernehmen und ausf\u00fchren.<\/p>\n<p><\/p>\n<p>Um ein Chaos zu vermeiden, haben wir unsere Projektgruppe auf einen GitLab Runner beschr\u00e4nkt, der mit unserem Volumen problemlos zurechtkommt.<\/p>\n<p><\/p>\n<p>Wir haben den Nginx-Proxy in ein separates Startskript ausgelagert und darin die Netzwerke aller Projekte definiert. <\/p>\n<p><\/p>\n<p>Unser Projekt verf\u00fcgt \u00fcber ein Netzwerk, w\u00e4hrend der Load-Balancer mehrere Netzwerke basierend auf den Projekt-Namen hat. Er kann auch \u00fcber Domainnamen weiter proxen.<\/p>\n<p><\/p>\n<p>Die Anfragen gelangen \u00fcber die Domain auf Port 80 und werden an eine Gruppe von Containern weitergeleitet, die diese Domain bedient.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/25c769f029b272a17fd06bbe60cf0ea0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Gab es noch andere Probleme? Standardm\u00e4\u00dfig laufen alle Container unter dem Benutzer root. Dieser root ist jedoch nicht dasselbe wie der root des Hostsystems.<\/p>\n<p><\/p>\n<p>Wenn man jedoch in den Container einsteigt, ist man root und die Dateien, die wir in diesem Container erstellen, erhalten root-Rechte.<\/p>\n<p><\/p>\n<p>Falls der Entwickler in den Container eingegangen ist und dort Befehle ausgef\u00fchrt hat, die Dateien erzeugen, hat er beim Verlassen des Containers in seinem Arbeitsverzeichnis Dateien, auf die er keinen Zugriff hat.<\/p>\n<p><\/p>\n<p>Wie kann man das l\u00f6sen? Man k\u00f6nnte Benutzer hinzuf\u00fcgen, die im Container arbeiten.<\/p>\n<p><\/p>\n<p>Welche Probleme traten auf, als wir einen Benutzer hinzugef\u00fcgt haben?<\/p>\n<p><\/p>\n<p>Wenn wir einen Benutzer erstellen, stimmen oft die Gruppen-ID (UID) und die Benutzer-ID (GID) nicht \u00fcberein.<\/p>\n<p><\/p>\n<p>Um dieses Problem im Container zu beheben, verwenden wir Benutzer mit der ID 1000.<\/p>\n<p><\/p>\n<p>In unserem Fall stimmt es, dass nahezu alle Entwickler Ubuntu als Betriebssystem verwenden. Bei Ubuntu hat der erste Benutzer die ID 1000.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/d4911374e4953fdcd807c387efeafec3.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Was sind unsere Pl\u00e4ne?<\/p>\n<p><\/p>\n<p>Die Dokumentation zu Docker noch einmal durchlesen. Das Projekt entwickelt sich aktiv und die Dokumentation \u00e4ndert sich. Die Informationen, die vor zwei oder drei Monaten gesammelt wurden, sind mittlerweile etwas veraltet. <\/p>\n<p><\/p>\n<p>Einige der Probleme, die wir gel\u00f6st haben, k\u00f6nnten bereits mit den Standardmethoden behoben worden sein.<\/p>\n<p><\/p>\n<p>Es w\u00e4re gro\u00dfartig, weiterzugehen und direkt zur Orchestrierung \u00fcberzugehen.<\/p>\n<p><\/p>\n<p>Ein Beispiel daf\u00fcr ist der in Docker integrierte Mechanismus namens Docker Swarm, der standardm\u00e4\u00dfig verf\u00fcgbar ist. Ich m\u00f6chte etwas in der Produktion mit Docker Swarm-Technologie starten.<\/p>\n<p><\/p>\n<p>Das Erstellen von Containern erschwert die Arbeit mit Logs. Momentan sind die Logs isoliert und \u00fcber die Container verstreut. Eine der Aufgaben besteht darin, einen einfachen Zugriff auf die Logs \u00fcber eine Web-Oberfl\u00e4che zu erm\u00f6glichen.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Der Entwicklungs- und Testprozess mit Docker und GitLab CI\" src=\"\/wp-content\/uploads\/2019\/04\/cff8c72dd8af7de1fa0227601bd1d69c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Quelle: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/449742\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0421\u0438\u0433\u0430\u0447\u0435\u0432\u0430 \u0438\u0437 Inventos &#171;\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker + Gitlab CI&#187; \u0422\u0435, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 Docker + Gitlab CI \u0447\u0430\u0441\u0442\u043e \u0441\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b. \u0421 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c? \u041a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c? \u041a\u0430\u043a \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c? \u042d\u0442\u043e\u0442 \u0434\u043e\u043a\u043b\u0430\u0434 \u0445\u043e\u0440\u043e\u0448 \u0442\u0435\u043c, \u0447\u0442\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":24326,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-32526","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0421\u0438\u0433\u0430\u0447\u0435\u0432\u0430 \u0438\u0437 Inventos &quot;\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker + Gitlab CI&quot; \u0422\u0435, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 Docker + Gitlab CI \u0447\u0430\u0441\u0442\u043e \u0441\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b. \u0421 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c? \u041a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c? \u041a\u0430\u043a \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c? \u042d\u0442\u043e\u0442 \u0434\u043e\u043a\u043b\u0430\u0434 \u0445\u043e\u0440\u043e\u0448 \u0442\u0435\u043c, \u0447\u0442\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker \u0438 Gitlab CI | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0421\u0438\u0433\u0430\u0447\u0435\u0432\u0430 \u0438\u0437 Inventos &quot;\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker + Gitlab CI&quot; \u0422\u0435, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 Docker + Gitlab CI \u0447\u0430\u0441\u0442\u043e \u0441\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b. \u0421 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c? \u041a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c? \u041a\u0430\u043a \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c? \u042d\u0442\u043e\u0442 \u0434\u043e\u043a\u043b\u0430\u0434 \u0445\u043e\u0440\u043e\u0448 \u0442\u0435\u043c, \u0447\u0442\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:47:32+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:47:32+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Entwicklungs- und Testprozess mit Docker und GitLab CI | ProHoster","description":"Ich lade Sie ein, die Zusammenfassung des Berichts von Alexander Sigachev von Inventos \u00fcber den \"Entwicklungs- und Testprozess mit Docker + GitLab CI\" zu lesen. Diejenigen, die gerade beginnen, den Entwicklungs- und Testprozess auf Basis von Docker + GitLab CI einzuf\u00fchren, haben oft grundlegende Fragen: Wo fange ich an? Wie organisiere ich es? Wie teste ich? Dieser Bericht ist besonders hilfreich, da er strukturiert \u00fcber den Entwicklungsprozess informiert und","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker \u0438 Gitlab CI | ProHoster","og:description":"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0421\u0438\u0433\u0430\u0447\u0435\u0432\u0430 \u0438\u0437 Inventos &quot;\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker + Gitlab CI&quot; \u0422\u0435, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 Docker + Gitlab CI \u0447\u0430\u0441\u0442\u043e \u0441\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b. \u0421 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c? \u041a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c? \u041a\u0430\u043a \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c? \u042d\u0442\u043e\u0442 \u0434\u043e\u043a\u043b\u0430\u0434 \u0445\u043e\u0440\u043e\u0448 \u0442\u0435\u043c, \u0447\u0442\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438","og:url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:47:32+00:00","article:modified_time":"2019-10-31T18:47:32+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"32526","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 11:18:24","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 02:57:22","updated":"2026-01-21 11:18:24"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/32526","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=32526"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/32526\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/24326"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=32526"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=32526"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=32526"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}