{"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 ein, den Bericht von Alexander Sigachev von Inventos \u00fcber den \"Entwicklungs- und Testprozess mit Docker + Gitlab CI\" zu lesen.<\/strong><\/p>\n<p><\/p>\n<p>Diejenigen, die gerade erst damit beginnen, den Entwicklungs- und Testprozess auf Basis von Docker + Gitlab CI einzuf\u00fchren, stellen oft grundlegende Fragen. Wo soll man anfangen? Wie soll man organisieren? Wie testen?<\/p>\n<p><\/p>\n<p>Dieser Bericht ist gut, weil er strukturiert \u00fcber den Entwicklungs- und Testprozess mit Docker und Gitlab CI spricht. Der Bericht stammt aus dem Jahr 2017. Ich denke, dass man aus diesem Bericht 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>F\u00fcr Interessierte bitte weiterlesen. <noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><\/p>\n<p>Ich hei\u00dfe Alexander Sigachev. Ich arbeite bei der Firma Inventos. Ich werde \u00fcber meine Erfahrungen mit Docker und dar\u00fcber berichten, wie wir es schrittweise in Projekten im Unternehmen implementieren.<\/p>\n<p><\/p>\n<p>Thema des Berichts: 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 Bericht \u00fcber Docker. Zum Zeitpunkt des ersten Berichts nutzten wir Docker nur in der Entwicklung auf den Maschinen der Entwickler. Die Anzahl der Mitarbeiter, die Docker nutzten, lag bei etwa 2-3 Personen. Nach und nach haben wir Erfahrung gesammelt und sind etwas weitergekommen. Hier ist der Link zu unserem <noindex><a rel=\"nofollow\" href=\"https:\/\/www.slideshare.net\/gled\/docker-development-70411088\">ersten Bericht<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Was wird in diesem Bericht behandelt? Wir werden unsere Erfahrungen teilen, welche Stolpersteine wir aufgesammelt haben und wie wir bestimmte Probleme gel\u00f6st haben. Es war nicht \u00fcberall sch\u00f6n, aber es hat uns erm\u00f6glicht, voranzukommen.<\/p>\n<p><\/p>\n<p>Unser Motto: Dockerisiere 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 es in einem Unternehmen mehrere Teams gibt, ist der Programmierer eine gefragte Ressource. Es gibt Phasen, in denen ein Programmierer aus einem Projekt herausgerissen wird und f\u00fcr eine gewisse Zeit in ein anderes Projekt gegeben wird.<\/p>\n<p><\/p>\n<p>Damit der Programmierer schnell einsteigen kann, muss er den Quellcode des Projekts herunterladen und m\u00f6glichst schnell eine Umgebung einrichten, die es ihm erm\u00f6glicht, die Aufgaben dieses Projekts weiter voranzutreiben.<\/p>\n<p><\/p>\n<p>Normalerweise, wenn man von Null anf\u00e4ngt, wird in dem Projekt wenig Dokumentation gef\u00fchrt. Die Informationen zur Einrichtung haben nur die alten Hasen. Eigenst\u00e4ndig richten die Mitarbeiter ihren Arbeitsplatz in ein oder zwei Tagen ein. Um dies zu beschleunigen, haben wir Docker eingesetzt.<\/p>\n<p><\/p>\n<p>Der n\u00e4chste Grund sind die Standardisierungen der Einstellungen in der Entwicklung. Nach meiner Erfahrung zeigen die Entwickler immer Initiative. In jedem f\u00fcnften Fall wird eine benutzerdefinierte Domain eingef\u00fchrt, zum Beispiel vasya.dev. Nebenan sitzt Nachbar Petja, der die Domain petya.dev hat. Sie entwickeln eine Website oder eine Systemkomponente mit diesem Domainnamen.<\/p>\n<p><\/p>\n<p>Wenn das System w\u00e4chst und diese Domainnamen in die Konfigurationen gelangen, entsteht ein Konflikt zwischen den Entwicklungsumgebungen und der Weg zur 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 dem leeren Passwort root. Bei manchen verlangte beim Setup MySQL ein Passwort und es stellte sich heraus, dass es 123 war. Oft kommt es vor, dass die Datenbankkonfiguration st\u00e4ndig ge\u00e4ndert wurde, je nach den Commits des Entwicklers. Manche haben die Konfiguration korrigiert, andere nicht. Es gab Tricks, bei denen wir eine Testkonfiguration in die <code>.gitignore<\/code> und jeder Entwickler musste die Datenbank installieren. Das erschwerte den Startprozess. Man muss neben allem anderen auch an die Datenbank denken. Die Datenbank muss initialisiert, das Passwort muss angegeben, ein Benutzer muss festgelegt und eine Tabelle muss erstellt werden und so weiter.<\/p>\n<p><\/p>\n<p>Ein weiteres Problem sind die unterschiedlichen Versionen von Bibliotheken. Oft ist es so, dass der Entwickler mit verschiedenen Projekten arbeitet. Es gibt ein Legacy-Projekt, das vor f\u00fcnf Jahren (seit 2017) gestartet wurde. Zu Beginn wurde mit MySQL 5.5 gearbeitet. Es gibt auch moderne Projekte, bei denen wir versuchen, bereits modernere MySQL-Versionen wie 5.7 oder \u00e4lter (im Jahr 2017) zu implementieren.<\/p>\n<p><\/p>\n<p>Jeder, der mit MySQL arbeitet, wei\u00df, dass diese Bibliotheken Abh\u00e4ngigkeiten mit sich ziehen. Es ist ziemlich problematisch, zwei Datenbanken gleichzeitig zu starten. Zumindest ist es schwierig, alte Clients mit einer neuen Datenbank zu verbinden. Das f\u00fchrt seinerseits zu mehreren Problemen.<\/p>\n<p><\/p>\n<p>Das n\u00e4chste Problem tritt auf, wenn der Entwickler auf seinem lokalen Rechner arbeitet, wobei er lokale Ressourcen, lokale Dateien und lokalen RAM verwendet. Alle Interaktionen w\u00e4hrend der Entwicklung der L\u00f6sungen erfolgen im Rahmen dessen, dass alles auf einem einzigen Rechner funktioniert. Ein Beispiel w\u00e4re, wenn wir in der Produktion drei Backend-Server haben und der Entwickler Dateien im Root-Verzeichnis speichert, von wo aus nginx Dateien f\u00fcr die Anfragen abruft. Wenn dieser Code in die Produktion gelangt, liegt das Problem darin, dass die Datei nur auf einem der drei Server vorhanden ist.<\/p>\n<p><\/p>\n<p>Aktuell entwickelt sich der Bereich der Mikrodienste. Wenn wir unsere gro\u00dfen Anwendungen in kleinere, miteinander interagierende Komponenten aufteilen. Dies erm\u00f6glicht es, die Technologien f\u00fcr den jeweiligen Aufgabenstapel auszuw\u00e4hlen. Au\u00dferdem erlaubt es eine bessere Aufteilung der Arbeit und der Verantwortungsbereiche unter den Entwicklern.<\/p>\n<p><\/p>\n<p>Frontend-Entwickler, die in JS entwickeln, haben praktisch keinen Einfluss auf das Backend. Der Backend-Entwickler hingegen entwickelt in unserem Fall Ruby on Rails und st\u00f6rt die Frontend-Entwicklung nicht. Die Interaktion erfolgt \u00fcber APIs.<\/p>\n<p><\/p>\n<p>Als Bonus konnten wir mit Docker die Ressourcen auf Staging optimieren. Jedes Projekt ben\u00f6tigte aufgrund seiner Spezifikationen bestimmte Einstellungen. Physisch mussten entweder separate virtuelle Server bereitgestellt und individuell konfiguriert werden oder es war n\u00f6tig, eine variable Umgebung zu teilen, sodass die Projekte, je nach Version der Bibliotheken, sich gegenseitig beeinflussen konnten.<\/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 ein Bindeglied, das mehrere unserer Docker-Anwendungen zusammenf\u00fchrt.<\/li>\n<li>GitLab verwenden wir zur Speicherung des Quellcodes.<\/li>\n<li>GitLab-CI verwenden 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 wird dar\u00fcber berichten, wie wir Docker auf den Maschinen der Entwickler gestartet haben.<\/p>\n<p><\/p>\n<p>Der zweite Teil wird behandeln, wie wir mit GitLab interagieren, wie wir Tests durchf\u00fchren 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 ist eine Technologie, die es erm\u00f6glicht, die erforderlichen Komponenten (unter Verwendung eines deklarativen Ansatzes) zu beschreiben. Dies ist ein Beispiel f\u00fcr ein Dockerfile. Hier erkl\u00e4ren wir, dass wir von dem offiziellen Docker-Image Ruby:2.3.0 erben. Es enth\u00e4lt die installierte Ruby-Version 2.3. Wir installieren die ben\u00f6tigten Build-Bibliotheken und NodeJS. Wir beschreiben, dass wir ein Verzeichnis erstellen. <code>\/app<\/code>. Wir setzen das Verzeichnis app als Arbeitsverzeichnis fest. In dieses Verzeichnis legen wir die erforderlichen minimalen Gemfiles und Gemfile.lock. Anschlie\u00dfend f\u00fchren wir den Build der Projekte durch, die dieses Abbild der Abh\u00e4ngigkeiten installieren. Wir geben an, dass der Container bereit ist, auf dem externen Port 3000 zu lauschen. Der letzte Befehl ist der Befehl, der unsere Anwendung tats\u00e4chlich startet. Wenn wir den Projektstartbefehl ausf\u00fchren, wird die Anwendung versuchen, sich auszuf\u00fchren, und den angegebenen Befehl 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 minimales Beispiel einer docker-compose Datei. In diesem Fall zeigen wir, was mit der Verbindung von zwei Containern geschieht. Dies bezieht sich direkt auf den Datenbankservice und den Webservice. Unsere Webanwendungen ben\u00f6tigen in den meisten F\u00e4llen eine Datenbank als Backend zur Datenspeicherung. Da wir MySQL verwenden, handelt es sich um ein Beispiel mit MySQL \u2013 aber es steht nichts im Wege, eine andere Datenbank (PostgreSQL, Redis) zu verwenden.<\/p>\n<p><\/p>\n<p>Wir verwenden das offizielle Image MySQL 5.7.14 von Docker Hub ohne \u00c4nderungen. Das Image, das f\u00fcr unsere Webanwendung verantwortlich ist, wird aus dem aktuellen Verzeichnis erstellt. Es erstellt beim ersten Start unser Image. Danach wird der Befehl ausgef\u00fchrt, den wir hier verwenden. Wenn wir einen Schritt zur\u00fcckgehen, werden wir sehen, dass der Startbefehl \u00fcber Puma definiert wurde. Puma ist ein Dienst, der in Ruby geschrieben ist. Im zweiten Fall \u00fcberschreiben wir. Dieser Befehl kann beliebig sein, je nach unseren Bed\u00fcrfnissen oder Anforderungen.<\/p>\n<p><\/p>\n<p>Au\u00dferdem beschreiben wir, dass der Port auf der Entwicklungsmaschine des Entwicklers von 3000 auf den Port 3000 des Containers weitergeleitet werden muss. Dies erfolgt automatisch mithilfe von iptables und einem Mechanismus, der direkt in Docker eingebaut ist. <\/p>\n<p><\/p>\n<p>Der Entwickler kann sich, wie zuvor, an jede verf\u00fcgbare IP-Adresse wenden, zum Beispiel 127.0.0.1 lokal oder an die externe IP-Adresse der Maschine.<\/p>\n<p><\/p>\n<p>Die letzte Zeile besagt, dass der Webcontainer von dem DB-Container abh\u00e4ngt. Wenn wir den Webcontainer starten, wird docker-compose zun\u00e4chst unsere Datenbank starten. Nach dem Start der Datenbank (tats\u00e4chlich \u2013 nach dem Start des Containers! Die Bereitstellung der Datenbank wird dadurch nicht garantiert) startet unsere Anwendung, unser Backend.<\/p>\n<p><\/p>\n<p>Dies hilft, Fehler zu vermeiden, wenn die Datenbank nicht bereit ist, und erm\u00f6glicht es, Ressourcen zu sparen, wenn wir den Datenbankcontainer stoppen und damit Ressourcen f\u00fcr andere Projekte freigeben. <\/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 der Dockerisierung von Datenbanken im Projekt bringt. Wir dokumentieren die MySQL-Version bei allen Entwicklern. Das hilft, einige Fehler zu vermeiden, die auftreten k\u00f6nnen, wenn die Versionen voneinander abweichen, etwa durch \u00c4nderungen in der Syntax, Konfiguration und den Standardeinstellungen. Au\u00dferdem erm\u00f6glicht es, gemeinsame Hostnamen f\u00fcr die Datenbank, Login und Passwort festzulegen. Damit weichen wir von dem Zoo der Namen und Konflikte in den Konfigurationsdateien ab, die es fr\u00fcher gab. <\/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 auf schwache Maschinen eingestellt und die Leistung ist von Haus aus 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 des Python-, Ruby-, NodeJS- und PHP-Interpreters in der ben\u00f6tigten Version. Wir ben\u00f6tigen keinen Versionsmanager mehr. Fr\u00fcher verwendeten wir f\u00fcr Ruby ein rpm-Paket, das den Versionswechsel je nach Projekt erlaubte. Dank des Docker-Containers kann der Code sanft migriert und zusammen mit den Abh\u00e4ngigkeiten versioniert werden. Wir haben keine Probleme, die Version sowohl des Interpreters als auch des Codes zu verstehen. Um die Version zu aktualisieren, muss der alte Container abgeschaltet und ein neuer Container hochgefahren werden. Sollte etwas schiefgehen, k\u00f6nnen wir den neuen Container herunterfahren und den alten Container wieder hochfahren.<\/p>\n<p><\/p>\n<p>Nach dem Erstellen des Images werden die Container sowohl in der Entwicklungsumgebung als auch in der Produktionsumgebung identisch sein. Dies ist besonders relevant 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 letzte Projekt, das wir haben, ist auf ReactJS. Der Entwickler hat alle Container gestartet und entwickelte mit Hot-Reload.<\/p>\n<p><\/p>\n<p>Anschlie\u00dfend wird die Aufgabe zur Erstellung von JavaScript gestartet, und der kompilierte Code wird als statische Datei \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 habe ich das Schema unseres letzten Projekts dargestellt.<\/p>\n<p><\/p>\n<p>Welche Aufgaben wurden gel\u00f6st? Wir hatten die Notwendigkeit, ein System aufzubauen, das mit mobilen Ger\u00e4ten interagiert. Diese erhalten Daten. Eine der M\u00f6glichkeiten ist das Versenden von Push-Benachrichtigungen an dieses Ger\u00e4t. <\/p>\n<p><\/p>\n<p>Was haben wir daf\u00fcr getan?<\/p>\n<p><\/p>\n<p>Wir haben die Anwendung in Komponenten unterteilt, darunter: den Administrationsbereich in JS, das Backend, das \u00fcber eine REST-API unter Ruby on Rails l\u00e4uft. Das Backend interagiert mit der Datenbank. Die Ergebnisse, die generiert werden, werden an den Client \u00fcbergeben. Die Admin-Oberfl\u00e4che kommuniziert mit dem Backend und der Datenbank \u00fcber die REST-API.<\/p>\n<p><\/p>\n<p>Wir hatten auch die Notwendigkeit, Push-Benachrichtigungen zu senden. Zuvor hatten wir ein Projekt, in dem ein Mechanismus implementiert war, der f\u00fcr die Zustellung von Benachrichtigungen auf mobilen Plattformen zust\u00e4ndig war. <\/p>\n<p><\/p>\n<p>Wir haben folgendes Schema entwickelt: Der Betreiber interagiert \u00fcber den Browser mit dem Admin-Bereich, der Admin-Bereich interagiert mit dem Backend und es wird die Aufgabe gestellt, 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>Es werden Warteschlangen aufgebaut und anschlie\u00dfend erfolgt die Zustellung der Benachrichtigungen nach ihrem Mechanismus.<\/p>\n<p><\/p>\n<p>Hier sind zwei Datenbanken skizziert. Im Moment nutzen wir mithilfe von Docker zwei unabh\u00e4ngige Datenbanken, die nicht miteinander verbunden sind, abgesehen von ihrem gemeinsamen virtuellen Netzwerk, w\u00e4hrend die physischen Daten in verschiedenen Verzeichnissen auf dem Rechner des Entwicklers gespeichert 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\/dfde59db7e6886d2d851dcf884049318.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dasselbe, aber in Zahlen. Hier ist die Wiederverwendbarkeit des Codes wichtig.<\/p>\n<p><\/p>\n<p>W\u00e4hrend wir zuvor \u00fcber die Wiederverwendbarkeit von Code in Form von Bibliotheken sprachen, wird unser Service f\u00fcr Push-Benachrichtigungen in diesem Beispiel als vollst\u00e4ndiger Server wiederverwendet. Er bietet eine API an. Mit dieser interagiert unsere neue Entwicklung.<\/p>\n<p><\/p>\n<p>Zu diesem Zeitpunkt verwendeten wir Version 4 von NodeJS. Jetzt (im Jahr 2017 \u2013 Anm. d. Red.) verwenden wir in neuen Entwicklungen Version 7 von NodeJS. Es gibt keine Probleme, neue Versionen von Bibliotheken in neuen Komponenten zu verwenden. <\/p>\n<p><\/p>\n<p>Bei Bedarf kann eine Refaktorisierung durchgef\u00fchrt werden, um die Version von NodeJS im Service f\u00fcr Push-Benachrichtigungen zu heben. <\/p>\n<p><\/p>\n<p>Wenn wir die Kompatibilit\u00e4t der API beibehalten k\u00f6nnen, k\u00f6nnte es m\u00f6glich sein, sie 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 ist n\u00f6tig, um Docker hinzuzuf\u00fcgen? Wir f\u00fcgen unserem Repository eine Dockerfile hinzu, die die notwendigen Abh\u00e4ngigkeiten beschreibt. In diesem Beispiel sind die Komponenten nach Logik unterteilt. Dies ist das minimale Set f\u00fcr Backend-Entwickler.<\/p>\n<p><\/p>\n<p>Bei der Erstellung eines neuen Projekts erstellen wir eine Dockerfile und beschreiben das erforderliche \u00d6kosystem (Python, Ruby, NodeJS). In der docker-compose beschreiben wir die notwendige Abh\u00e4ngigkeit \u2013 die Datenbank. Wir geben an, dass eine Datenbank dieser Version ben\u00f6tigt wird, um die Daten dort zu speichern.<\/p>\n<p><\/p>\n<p>Wir verwenden einen separaten dritten Container mit nginx f\u00fcr die Bereitstellung von Statischen Inhalten. Es ist die M\u00f6glichkeit vorgesehen, Bilder hochzuladen. Der Backend platziert sie in einem zuvor vorbereiteten Volume, das ebenfalls in den Container mit nginx montiert 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 erforderlichen Konfigurationen aufbewahren. Wenn ein Entwickler das Git-Repository auf seinen Computer klont, erh\u00e4lt er ein Projekt, das bereits f\u00fcr die lokale Entwicklung bereit ist. Es stellt sich nicht die Frage, welchen 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 alles zu starten, haben wir ein weiteres Repository erstellt, das wir dockerized-app genannt haben. Im Moment verwenden wir mehrere Repositories f\u00fcr jede Komponente. Sie unterscheiden sich einfach logisch \u2013 in GitLab sieht das wie ein Ordner aus, und auf dem Computer des Entwicklers gibt es einen Ordner f\u00fcr ein bestimmtes Projekt. Auf einer tieferen Ebene liegen die Komponenten, die zusammengef\u00fchrt 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>Dies ist ein Beispiel f\u00fcr den Inhalt von dockerized-app. Wir nehmen auch das Docker-Verzeichnis hier heraus, in dem wir die Konfigurationen sammeln, die f\u00fcr die Interaktion aller Komponenten erforderlich sind. Es gibt eine README.md, die kurz beschreibt, wie man das Projekt startet.<\/p>\n<p><\/p>\n<p>Hier haben wir zwei Docker-Compose-Dateien verwendet. Dies wurde gemacht, um die M\u00f6glichkeit zu haben, schrittweise zu starten. Wenn ein Entwickler am Kern arbeitet und keine Push-Benachrichtigungen ben\u00f6tigt, startet er einfach die Docker-Compose-Datei, und entsprechend werden Ressourcen eingespart.<\/p>\n<p><\/p>\n<p>Wenn es notwendig ist, sich mit Push-Benachrichtigungen zu integrieren, wird die docker-compose.yaml und 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 erweiterte Datei, die f\u00fcr den Zusammenbau der Komponenten verantwortlich ist. Was dabei bemerkenswert ist? Hier f\u00fchren wir die Lastverteilungskomponente ein.<\/p>\n<p><\/p>\n<p>Dies ist ein fertiges Docker-Image, in dem Nginx und eine Anwendung gestartet werden, die den Docker-Socket \u00fcberwacht. Dynamisch, je nach Ein- und Ausschalten der Container, wird die Nginx-Konfiguration neu generiert. Der Zugang zu den Komponenten erfolgt \u00fcber Subdomains.<\/p>\n<p><\/p>\n<p>F\u00fcr die Entwicklungsumgebung verwenden wir die Domain .dev \u2013 api.informer.dev. Anwendungen mit der Domain .dev sind auf dem lokalen Computer des Entwicklers verf\u00fcgbar.<\/p>\n<p><\/p>\n<p>Dann werden die Konfigurationen f\u00fcr 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 ergibt sich, dass der Client unser Browser oder ein Tool ist, mit dem wir Anfragen an den Lastverteiler stellen.<\/p>\n<p><\/p>\n<p>Der Lastverteiler bestimmt anhand des Domainnamens, mit welchem Container er kommunizieren soll.<\/p>\n<p><\/p>\n<p>Das kann nginx sein, der die JS-Administration ausliefert. Das kann nginx sein, der die API oder statische Dateien ausliefert, die von nginx als Bild-Uploads bereitgestellt werden.<\/p>\n<p><\/p>\n<p>In dem Diagramm ist zu sehen, dass die Container in einem virtuellen Netzwerk zusammengefasst und hinter einem Proxy verborgen sind.<\/p>\n<p><\/p>\n<p>Auf dem Entwicklerrechner kann man auf den Container zugreifen, wenn man die IP kennt, aber das nutzen wir grunds\u00e4tzlich nicht. Die Notwendigkeit f\u00fcr einen direkten Zugriff entsteht praktisch nie.<\/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 anschauen, um seine Anwendung zu dockerisieren? Meiner Meinung nach ist ein gutes Beispiel das offizielle Docker-Image f\u00fcr MySQL.<\/p>\n<p><\/p>\n<p>Es ist ziemlich komplex. Es gibt viele Versionen. Aber seine Funktionalit\u00e4t erm\u00f6glicht es, viele Bed\u00fcrfnisse abzudecken, die w\u00e4hrend der weiteren Entwicklung entstehen k\u00f6nnen. Wenn Sie sich die Zeit nehmen und lernen, wie alles zusammenarbeitet, denke ich, dass Sie bei der eigenst\u00e4ndigen Implementierung keine Probleme haben werden.<\/p>\n<p><\/p>\n<p>Auf hub.docker.com sind normalerweise Links zu github.com vorhanden, wo die Rohdaten bereitgestellt werden, aus denen man selbst ein Image erstellen kann.<\/p>\n<p><\/p>\n<p>In diesem Repository befindet sich das Skript docker-endpoint.sh, das f\u00fcr die Erstinitialisierung und die weitere Verarbeitung des Anwendungsstarts verantwortlich ist.<\/p>\n<p><\/p>\n<p>In diesem Beispiel gibt es auch die M\u00f6glichkeit der Konfiguration \u00fcber Umgebungsvariablen. Indem man die Umgebungsvariablen beim Start eines einzelnen Containers oder \u00fcber docker-compose festlegt, kann man sagen, dass wir ein leeres Passwort f\u00fcr docker f\u00fcr root in MySQL oder ein beliebiges Passwort, das wir m\u00f6chten, festlegen m\u00fcssen.<\/p>\n<p><\/p>\n<p>Es besteht die M\u00f6glichkeit, ein zuf\u00e4lliges Passwort zu erstellen. Wir sagen, dass wir einen Benutzer ben\u00f6tigen, ein Passwort f\u00fcr den Benutzer festlegen und eine Datenbank erstellen m\u00fcssen.<\/p>\n<p><\/p>\n<p>In unseren Projekten haben wir das Dockerfile etwas standardisiert, das f\u00fcr die Initialisierung verantwortlich ist. Dort haben wir es nach unseren Bed\u00fcrfnissen angepasst, um einfach die Benutzerrechte zu erweitern, die die Anwendung ben\u00f6tigt. Das hat es uns erm\u00f6glicht, sp\u00e4ter einfach eine Datenbank \u00fcber die Anwendungs-Konsole 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 erfolgt.<\/p>\n<p><\/p>\n<p>Das Skript docker-endpoint.sh ist f\u00fcr den Einstiegspunkt verantwortlich. Bei der \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u043e\u0439 Initialisierung sind einige Vorbereitungsma\u00dfnahmen erforderlich, und all diese Ma\u00dfnahmen sind im Initialisierungsskript zusammengefasst.<\/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 gehen zum zweiten Teil \u00fcber.<\/p>\n<p><\/p>\n<p>F\u00fcr die Speicherung der Quellcodes haben wir auf GitLab umgestellt. Es ist ein leistungsf\u00e4higes System mit einer visuellen Benutzeroberfl\u00e4che.<\/p>\n<p><\/p>\n<p>Einer der Komponenten von GitLab ist GitLab CI. Damit kann man eine Abfolge von Befehlen beschreiben, die anschlie\u00dfend verwendet werden, um das Code-Deployment oder die Durchf\u00fchrung automatischer Tests zu organisieren.<\/p>\n<p><\/p>\n<p>Bericht \u00fcber GitLab CI 2 <noindex><a rel=\"nofollow\" href=\"https:\/\/goo.gl\/uohKjI\">https:\/\/goo.gl\/uohKjI<\/a><\/noindex> \u2014 Bericht vom Ruby Russia Club \u2014 ist ziemlich detailliert und k\u00f6nnte Sie interessieren.<\/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 sehen wir uns an, was ben\u00f6tigt wird, um GitLab CI zu aktivieren. Um GitLab CI zu starten, reicht es aus, die Datei .gitlab-ci.yml ins Wurzelverzeichnis des Projekts zu legen.<\/p>\n<p><\/p>\n<p>Hier beschreiben wir, welche Abfolge von Status wie Tests und Deployments wir ausf\u00fchren m\u00f6chten.<\/p>\n<p><\/p>\n<p>Wir f\u00fchren Skripte aus, die die docker-compose-Build unseres Anwendungs-Backends direkt aufrufen. Das ist ein Beispiel f\u00fcr das Backend.<\/p>\n<p><\/p>\n<p>Anschlie\u00dfend geben wir an, dass Migrationen zur Datenbank\u00e4nderung durchgef\u00fchrt und 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 einen reibungslosen Neustart nicht organisiert.<\/p>\n<p><\/p>\n<p>Wir stoppen gezielt alle Container 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 die Migrationen der Datenbanken f\u00fcr die aktuelle variable Umgebung 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 soll.<\/p>\n<p><\/p>\n<p>Bei \u00c4nderungen an anderen Branches erfolgt dies nicht.<\/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 GitLab Runner installieren.<\/p>\n<p><\/p>\n<p>Dieses Tool ist in Golang geschrieben. Es handelt sich um eine Einzeldatei, wie es in der Golang-Welt \u00fcblich ist, ohne dass Abh\u00e4ngigkeiten erforderlich sind.<\/p>\n<p><\/p>\n<p>Bei der Ausf\u00fchrung registrieren wir den GitLab Runner.<\/p>\n<p><\/p>\n<p>Im Webinterface von GitLab erhalten wir einen Schl\u00fcssel.<\/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 der .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. Nachdem wir Gitlab CI verbunden haben, erscheint eine Flagge, die anzeigt, in welchem Zustand sich der Build derzeit befindet.<\/p>\n<p><\/p>\n<p>Wir sehen, dass vor 4 Minuten ein Commit gemacht 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 uns die Builds detaillierter ansehen. Hier sehen wir, dass bereits zwei Zust\u00e4nde durchlaufen wurden: den Test- und den Deploy-Zustand auf Staging.<\/p>\n<p><\/p>\n<p>Wenn wir auf einen bestimmten Build klicken, wird es eine Konsolenausgabe der Befehle geben, die im Prozess 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 es erfolgreiche Versuche gab. Wenn die Tests fehlerhaft sind, wird nicht zum n\u00e4chsten Schritt \u00fcbergegangen 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 Aufgaben haben wir auf Staging gel\u00f6st, als wir Docker implementiert haben? Unser System besteht aus Komponenten und wir hatten die Notwendigkeit, nur die Teile der Komponenten, die im Repository aktualisiert wurden, neu zu starten, 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 getan hatten, hatten wir das Problem, dass Docker-Compose f\u00fcr jeden Ordner sein eigenes Netzwerk erstellt, und die Komponenten der Nachbarn nicht sehen kann.<\/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 f\u00fcr dieses Projekt dieses Netzwerk verwendet werden soll.<\/p>\n<p><\/p>\n<p>Auf diese Weise sieht jede Komponente, die mit diesem Netzwerk gestartet wird, die Komponenten in anderen Teilen des Systems.<\/p>\n<p><\/p>\n<p>Das n\u00e4chste Problem ist die Trennung von Staging zwischen mehreren Projekten.<\/p>\n<p><\/p>\n<p>Damit alles sch\u00f6n aussieht und so nah wie m\u00f6glich an der Produktion ist, ist es gut, den Port 80 oder 443 zu verwenden, der im Web allgemein genutzt wird.<\/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 gro\u00dfen Projekte zugewiesen.<\/p>\n<p><\/p>\n<p>Gitlab erlaubt es, mehrere verteilte Gitlab Runner zu starten, die einfach der Reihe nach, in zuf\u00e4lliger Reihenfolge, alle Aufgaben abarbeiten.<\/p>\n<p><\/p>\n<p>Um kein Chaos zu verursachen, haben wir die Gruppe unserer Projekte auf einen Gitlab Runner beschr\u00e4nkt, der mit unseren Volumen problemlos zurechtkommt.<\/p>\n<p><\/p>\n<p>Wir haben nginx-proxy in ein separates Startskript ausgelagert und in diesem die Netzwerke aller Projekte festgelegt. <\/p>\n<p><\/p>\n<p>Unser Projekt hat ein Netzwerk, w\u00e4hrend der Balancer mehrere Netzwerke nach Projektnamen hat. Er kann weiter nach Domainnamen proxy.<\/p>\n<p><\/p>\n<p>Wir erhalten Anfragen \u00fcber die Domain auf Port 80, die in eine Gruppe von Containern geleitet werden, die diese Domain bedienen.<\/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>Welche weiteren Probleme gab es? Standardm\u00e4\u00dfig werden alle Container als Benutzer root ausgef\u00fchrt. Dieses root ist nicht gleich dem root des Hosts.<\/p>\n<p><\/p>\n<p>Wenn man jedoch in den Container einloggt, ist man root, und die Datei, die wir in diesem Container erstellen, erh\u00e4lt die Berechtigungen von root.<\/p>\n<p><\/p>\n<p>Wenn der Entwickler in den Container eingeloggt ist und dort Befehle ausf\u00fchrt, die Dateien erzeugen, und dann den Container verl\u00e4sst, hat er in seinem Arbeitsverzeichnis eine Datei, 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>Beim Erstellen eines Benutzers stimmen oft die Gruppen-ID (UID) und die Benutzer-ID (GID) nicht \u00fcberein.<\/p>\n<p><\/p>\n<p>Um dieses Problem zu l\u00f6sen, verwenden wir im Container Benutzer mit der ID 1000.<\/p>\n<p><\/p>\n<p>In unserem Fall stimmte das damit \u00fcberein, dass fast alle Entwickler das Betriebssystem Ubuntu 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 nochmal durchlesen. Das Projekt entwickelt sich aktiv weiter, die Dokumentation \u00e4ndert sich. Daten, die vor zwei bis drei Monaten erhalten wurden, sind allm\u00e4hlich schon veraltet. <\/p>\n<p><\/p>\n<p>Ein Teil der Probleme, die wir gel\u00f6st haben, k\u00f6nnte bereits mit Standardmitteln gel\u00f6st worden sein.<\/p>\n<p><\/p>\n<p>Wir m\u00f6chten gerne weitergehen und direkt zur Orchestrierung \u00fcbergehen.<\/p>\n<p><\/p>\n<p>Ein Beispiel ist der in Docker integrierte Mechanismus namens Docker Swarm, der standardm\u00e4\u00dfig verf\u00fcgbar ist. Wir m\u00f6chten etwas im Produktionsbetrieb auf der Basis der Docker Swarm-Technologie starten.<\/p>\n<p><\/p>\n<p>Die Erzeugung von Containern macht die Arbeit mit Logs unpraktisch. Momentan sind die Logs isoliert. Sie sind \u00fcber die Container verstreut. Eine der Aufgaben besteht darin, einen komfortablen Zugang zu den Logs \u00fcber ein Web-Interface zu schaffen.<\/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 5.0.1.1 - 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.\" \/>\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) 5.0.1.1\" \/>\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.\" \/>\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\udd47Entwicklung und Testen mit Docker und Gitlab CI | ProHoster","description":"Ich lade Sie ein, den Bericht von Alexander Sigachev von Inventos \"Prozess der Entwicklung und Testung mit Docker + Gitlab CI\" zu lesen. Diejenigen, die gerade beginnen, den Entwicklungsprozess einzuf\u00fchren 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.","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","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"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}]}}