Vollautomatisierte Entwicklungsumgebung mit Docker-Compose

Ursprünglicher Autor: Andrew Orsich
  • Übersetzung

Laut Ben Golub, CEO von Docker , der auf der Dockercon 2016 präsentierte , ist die Anzahl der in Docker-Containern ausgeführten Anwendungen in den letzten zwei Jahren um 3100% gestiegen. Docker bietet weltweit 460.000 Anwendungen. Das ist unglaublich!


Wenn Sie Docker noch nicht verwendet haben, lesen Sie dieses beeindruckende Einführungsdokument. Docker hat den Ansatz zum Erstellen von Anwendungen geändert und ist zu einem äußerst wichtigen Tool für Entwickler und DevOps-Experten geworden. Dieser Artikel richtet sich an Benutzer, die Docker bereits verwenden, und soll einen weiteren Grund aufzeigen, warum Sie dies weiterhin tun sollten.


Wir möchten unsere Erfahrungen mit Docker-Compose in großen Projekten teilen. Mithilfe dieses Tools zur Automatisierung von Aufgaben im Zusammenhang mit Entwicklung, Test und Konfiguration konnten wir in wenigen einfachen Schritten unser Team effizienter machen und uns direkt auf die Produktentwicklung konzentrieren.


Das problem


Zu Beginn meiner Karriere, als ich noch ein junger Entwickler bei c # und asp.net war, war die Bereitstellung einer Entwicklungsumgebung keine leichte Aufgabe. Es war erforderlich, Datenbanken und Tools zu installieren, die für das Funktionieren der Anwendung erforderlich sind. In diesem Fall mussten die Konfigurationsdateien so geändert werden, dass sie den Einstellungen des lokalen Computers entsprachen. Ich musste Ports, Pfade zu lokalen Verzeichnissen mit Updates usw. registrieren. Diese Schritte waren in der Regel schlecht dokumentiert, sodass das Starten der Entwicklungsumgebung sehr viel Zeit in Anspruch nahm.


Viele Produkte zu Beginn ihrer Entwicklung sind nicht schwierig, aber wenn neue Funktionen implementiert werden, wird es schwieriger, mit ihnen umzugehen. Sie fügen neue Tools und Subsysteme hinzu, z. B. zusätzliche Datenbanken und Nachrichtenwarteschlangen. Aufgrund der wachsenden Popularität von Microservices werden monolithische Monster mit großen Anwendungen zunehmend in viele Teile geteilt. Solche Änderungen erfordern normalerweise die Teilnahme des gesamten Teams, das an dem Projekt arbeitet. Ein Entwickler, der Änderungen an lokalen Umgebungen vornimmt, schreibt normalerweise lange Briefe mit einer Liste der erforderlichen Konfigurationsschritte. Ich erinnere mich an den Fall, dass ein in Übersee tätiger Spezialist eine gravierende Änderung in der Struktur des Produkts vorgenommen hat, einen Brief mit Anweisungen zur Wiederherstellung der Arbeitsfähigkeit der lokalen Umgebung geschrieben hat und eingeschlafen ist. Ich denke, Sie haben erraten, was als nächstes passiert ist. Richtig: Er vergaß einige wichtige Punkte zu erwähnen. Infolgedessen verlor der Großteil des Teams am nächsten Arbeitstag den Versuch, den aktualisierten Code für die Arbeit in der lokalen Arbeitsumgebung bereitzustellen.


Entwickler schreiben Dokumentation sehr (nicht) gern, und einige Schritte zum Starten eines Projekts werden häufig ausschließlich in ihrem Kopf gespeichert. Das Einrichten einer Arbeitsumgebung von Grund auf ist daher eine nicht triviale Aufgabe, insbesondere für Anfänger.


Wie jeder Ingenieur bemühe ich mich, alles um mich herum zu automatisieren. Ich bin davon überzeugt, dass das Starten, Testen und Bereitstellen der Anwendung in einem Schritt erfolgen sollte. So kann sich das Team auf wirklich wichtige Dinge konzentrieren: Produktentwicklung und -verbesserung. Vor zehn Jahren war die Automatisierung dieser Aufgaben viel schwieriger als heute. Jetzt kann und sollte es jeder tun, und je früher Sie anfangen, desto besser.


Schnellstart mit Docker-Compose


Docker-compose ist ein einfaches Tool, mit dem Sie mehrere Docker-Container mit einem Befehl ausführen können. Bevor ich ins Detail gehe, muss ich über die Struktur des Projekts sprechen. Wir verwenden monorepo und die Codebasis jedes Dienstes (Webanwendung, API, Hintergrundhandler) wird in seinem Stammverzeichnis gespeichert. Jeder Dienst verfügt über eine Docker-Datei, die seine Abhängigkeiten beschreibt. Ein Beispiel für eine solche Struktur finden Sie in unserem Demo-Projekt .


Beginnen wir mit der Automatisierung einer einfachen Anwendung, die von MongoDB und einem kleinen Dienst von Node.JS abhängt. Die Konfiguration für docker-compose befindet sich in der Datei docker-compose.yml, die sich normalerweise im Stammverzeichnis des Projekts befindet.


version: '2'  
services:  
  web:
    build:
      context: ./web
      dockerfile: Dockerfile.dev
    volumes:
      - "./web/src:/web/src"
    ports:
      - "8080:8080"
  mongo:
    command: mongod
    image: mongo:3.2.0
    ports:
      - "27100:27017" # map port to none standard port, to avoid conflicts with locally installed mongodb. 
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

Um ein Projekt zu starten, müssen Sie nur einen Befehl ausführen:


$ docker-compose up

Beim ersten Start werden alle notwendigen Container angelegt oder geladen. Auf den ersten Blick ist es nicht kompliziert, insbesondere wenn Sie früher mit Docker gearbeitet haben, aber noch einige Details besprechen:


  1. context: ./web - auf diese weise wird der pfad zum quellcode des dienstes innerhalb der monorepo angezeigt.
  2. dockerfile: Dockerfile.dev- Für Entwicklungsumgebungen verwenden wir eine separate Dockerfile.dev. In der Produktion wird der Quellcode direkt in den Container kopiert und für die Entwicklung als Volume verbunden. Daher muss der Container nicht bei jeder Codeänderung neu erstellt werden.
  3. volumes: - "./web/src:/web/src" - auf diese weise wird das verzeichnis mit dem code als volume zum docker hinzugefügt.
  4. Docker-compose ordnet Container automatisch einander zu, sodass beispielsweise ein Webdienst namentlich auf mongodb zugreifen kann: mongodb://mongo:27017

Verwenden Sie immer ein Argument --build


Wenn sich die Container bereits auf dem Host befinden, werden docker-compose upsie standardmäßig nicht neu erstellt. Um diese Operation zu erzwingen, wird ein Argument verwendet --build. Dies ist erforderlich, wenn sich Abhängigkeiten von Drittanbietern oder die Docker-Datei selbst ändern. Wir haben es uns zur Regel gemacht, immer zu befolgen docker-compose up --build. Docker speichert Container-Layer perfekt zwischen und erstellt sie nicht neu, wenn sich nichts geändert hat. Ständige Verwendung --buildkann den Download für einige Sekunden verlangsamen, schützt jedoch vor unerwarteten Problemen beim Ausführen der Anwendung mit veralteten Abhängigkeiten von Drittanbietern.


Tipp: Sie können den Start des Projekts mit einem einfachen Skript abstrahieren:


#!/bin/sh
docker-compose up --build "$@"  

Mit dieser Technik können Sie bei Bedarf die beim Start verwendeten Optionen und Tools ändern. Oder du kannst es einfach tun ./bin/start.sh.


Teilstart


Im Beispiel docker-compose.yml hängen einige Dienste von anderen ab:


  api:
    build:
      context: ./api
      dockerfile: Dockerfile.dev
    volumes:
      - "./api/src:/app/src"
    ports:
      - "8081:8081"
    depends_on:
      - mongo

In diesem Fragment apibenötigt der Dienst eine Datenbank. Wenn die Docker-compose verwenden, können Sie den Namen des Dienstes angeben , um nur ihn zu laufen docker-compose up api. Dieser Befehl startet MongoDB und danach den API-Dienst. In großen Projekten können solche Funktionen nützlich sein.


Diese Funktionalität ist nützlich, wenn verschiedene Entwickler verschiedene Teile des Systems benötigen. Beispielsweise benötigt der Frontend-Spezialist, der an der Landing Page arbeitet, nicht das gesamte Projekt, nur die Landing Page selbst ist ausreichend.


Unnötige Logs in> / dev / null


Einige Programme erzeugen zu viele Protokolle. Diese Informationen sind in den meisten Fällen nutzlos und lenken nur ab. In unserem Demo-Repository haben wir MongoDB-Protokolle deaktiviert, indem wir den Protokolltreiber auf none gesetzt haben :


  mongo:
    command: mongod
    image: mongo:3.2.0
    ports:
      - "27100:27017"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    logging:
      driver: none

Mehrere Docker-Compose-Dateien


Nach dem Ausführen des Befehls docker-compose upwird standardmäßig nach der Datei docker-compose.ymlim aktuellen Verzeichnis gesucht .


In einigen Fällen (wir werden dies etwas später besprechen) werden möglicherweise mehrere Dateien benötigt docker-compose.yml. Um eine andere Konfigurationsdatei einzuschließen, kann das Argument verwendet werden --file:


docker-compose --file docker-compose.local-tests.yml up  

Warum brauchen wir also mehrere Konfigurationsdateien? Zuallererst, um ein zusammengesetztes Projekt in mehrere Teilprojekte aufzuteilen. Ich bin froh, dass noch Dienste aus verschiedenen Compose-Dateien verbunden werden können. Beispielsweise können Sie infrastrukturbezogene Container (Datenbanken, Warteschlangen usw.) in eine Docker-Compose-Datei und anwendungsbezogene Container in eine andere einfügen.


Testen


Wir verwenden verschiedene Arten von Tests: Unit, Integrational, UI, Linting. Für jeden Dienst wurde eine separate Reihe von Tests entwickelt. Beispielsweise erfordern Integrations- und UI-Tests die Ausführung von API- und Webdiensten.


Zuerst hielten wir es für besser, Tests jedes Mal auszuführen, wenn die Hauptkompositionsdatei ausgeführt wurde, stellten jedoch schnell fest, dass dies zeitaufwändig war. In einigen Fällen mussten wir in der Lage sein, bestimmte Tests durchzuführen. Hierfür wurde eine separate Compose-Datei erstellt:


version: '2'  
services:  
  api-tests:
    image: app_api
    command: npm run test
    volumes:
      - "./api/src:/app/src"
  web-tests:
    image: app_web
    command: npm run test
    volumes:
      - "./web/src:/app/src"

Unsere Test-Compose-Datei hängt von der wichtigsten Docker-Compose- Datei ab. Integrationstests stellen eine Verbindung zur Entwicklungsversion her api, UI- Tests stellen eine Verbindung her web frontend. In der Test-Compose-Datei werden nur die Container ausgeführt, die in der Haupt-Docker-Compose-Datei erstellt wurden. Wenn Sie Tests nur für einen Dienst ausführen möchten, können Sie einen Teillauf verwenden:


docker-compose --file docker-compose.local-tests.yml up api-tests  

Dieser Befehl führt nur Tests für aus api.


Präfixe für Containernamen


По умолчанию всем контейнерам, запущенным с помощью docker-compose, присваивается префикс в виде имени родительской директории. Имя директории в различных средах разработки может меняться. Из-за этого Docker-compose-файлы с тестами, о которых мы говорили ранее, могут перестать работать. Мы используем префикс (app_) для контейнеров в основном файле docker-compose. Для согласованной работы конфигурации в различных средах мы создали специальный .env-файл в директории, в которой запускаем docker-compose:


COMPOSE_PROJECT_NAME=app  

Таким образом можно добиться того, что контейнерам будут присваиваться одинаковые префиксы во всех окружениях вне зависимости от имени родительской директории.


Заключение


Docker-compose — это полезный и гибкий инструмент для запуска ПО, используемого для работы над проектами.


Wenn neue Entwickler zu uns kommen, geben wir ihnen normalerweise am ersten Tag die Aufgabe, eine einfache Funktion in die Produktion einzuführen oder einen Fehler zu beheben. Unsere Kurzanleitung sieht ungefähr so ​​aus:


1) Docker und Docker-compose installieren ,
2) das GitHub-Repository kopieren,
3) einen Befehl im Terminal ausführen ./bin/start.sh.


Um die in diesem Artikel vorgestellten Konzepte besser zu verstehen, empfehlen wir Ihnen, sich das auf GitHub veröffentlichte Demo-Projekt anzuschauen . Teile deine Erfahrungen und stelle Fragen .


Wir hoffen, dass Sie diesen Artikel nützlich fanden und die erhaltenen Informationen helfen, Ihre Projekte zu verbessern :)


Original: Vollautomatisierte Entwicklungsumgebung mit Docker-Compose


Jetzt auch beliebt: