Loading...
Docker Compose-Setups als eigenständige Container ausführen

Docker Compose-Setups als eigenständige Container ausführen

Lukas Mauser - Co-Founder von sliplane.ioLukas Mauser
9 min

Docker Compose ist großartig! Aber manchmal kann es nützlich sein, eine docker-compose.yml-Datei zu entschlüsseln und jeden Container einzeln auszuführen.

Wir betreiben eine Hosting-Plattform für Container, unterstützen aber noch kein Docker Compose. Wir bekommen viele Anfragen, wie man Docker Compose-Setups deployen kann. Daher möchte ich dir den Prozess erklären, wie du eine Docker Compose-Datei dekonstruieren kannst, um jeden Container einzeln auszuführen.

Kurz gesagt:

Um Docker Compose-Setups als eigenständige Apps auszuführen, musst du zuerst alle definierten Services und alle Ressourcen identifizieren, die jeder einzelne Service verwendet, wie Volumes, Netzwerke und Umgebungseinstellungen. Beginne damit, diese Ressourcen einzeln zu erstellen, und sobald alles eingerichtet ist, leite docker build ... und docker run ...-Befehle für jeden Service ab.

Wenn du in der Cloud deployest und eine Plattform wie Sliplane verwendest, reicht es normalerweise aus, einfach die Konfiguration für jeden Service bereitzustellen.

Schauen wir uns den Prozess genauer an.

Grundlegende Docker-Konzepte

Bevor wir beginnen, solltest du die wichtigsten Docker-Konzepte verstehen. Wenn du gerade mit Docker anfängst, empfehle ich dir, die offizielle Dokumentation im Docker Getting Started Guide durchzugehen. Versuche besonders zu verstehen:

Docker ist natürlich viel mehr als das, aber wenn du diese Grundkonzepte verstehst, wird es viel einfacher, Docker Compose-Dateien zu lesen und zu verstehen, und du wirst die meisten Setups zum Laufen bringen können!

Wie man Services aus einer docker-compose.yml-Datei einzeln ausführt

Schauen wir uns ein Beispiel für eine Docker Compose-Datei an, versuchen wir, sie zu dekonstruieren und das Setup als einzelne Container auszuführen:

version: "3.9"                                # Version von Docker Compose

services:                                      # Definition der Services (Container) für deine App
  app:                                         # Service-Name: app
    image: my-app:latest                       # Das Image für den App-Service (neueste Version)
    container_name: my_app_container            # Benutzerdefinierter Name für den Container
    build:
      context: ./app                           # Der Build-Kontext (Verzeichnis für das Dockerfile)
      dockerfile: Dockerfile                   # Das Dockerfile zum Erstellen des Images
      args:
        - APP_ENV=production                   # Build-Argument zum Setzen der Umgebungsvariable
    environment:
      - APP_ENV=production                     # Umgebungsvariable im Container setzen
      - APP_SECRET=mysecret                    # Weitere Umgebungsvariable für die App
    ports:
      - "8080:80"                              # Port 8080 auf dem Host zu Port 80 im Container mappen
    volumes:
      - app-data:/data                         # Volume-Mount für persistente App-Daten
    networks:
      - shared-network                         # App mit einem gemeinsamen Netzwerk verbinden
    depends_on:
      - db                                     # Sicherstellen, dass der DB-Service vor dem App-Service startet
      restart_policy:
        condition: on-failure                  # App neu starten, wenn sie fehlschlägt
    labels:
      com.example.description: "My web app"    # Benutzerdefiniertes Label zur Beschreibung der App

  db:                                          # Service-Name: db
    image: postgres:16                         # Offizielles PostgreSQL 16-Image verwenden
    container_name: my_db_container            # Benutzerdefinierter Name für den Datenbank-Container
    environment:
      POSTGRES_PASSWORD: password              # PostgreSQL-Passwort setzen
    volumes:
      - db-data:/var/lib/postgresql/data       # Volume-Mount für Datenbank-Datenpersistenz
    networks:
      - shared-network                         # DB mit dem gemeinsamen Netzwerk verbinden
    ports:
      - "5432:5432"                            # PostgreSQL-Standardport 5432 vom Container zum Host mappen

volumes:
  app-data:                                    # Benanntes Volume für App-Datenpersistenz
  db-data:                                     # Benanntes Volume für Datenbank-Datenpersistenz

networks:
  shared-network:                              # Ein gemeinsames Netzwerk für die Kommunikation beider Services definieren

Die Struktur von Docker Compose-Dateien wird in der offiziellen Compose-Dateireferenz beschrieben. In diesem Beispiel gibt es 4 Optionen auf oberster Ebene:

  • version
  • services
  • volumes und
  • networks.

version beschreibt nur die verwendete Version von Docker Compose, die wir in diesem Tutorial nicht benötigen.

Die zweite Option, services, ist hier am wichtigsten. Sie beschreibt die Konfiguration für jeden Container. In der obigen Compose-Datei gibt es 2 Services: app und db, die jeweils als Schlüssel innerhalb des services-Blocks dargestellt werden.

Bevor wir jedoch jeden Service einzeln ausführen können, müssen wir einige Vorbereitungen treffen.

Du kannst sehen, dass beide Service-Blöcke einen volumes- und networks-Abschnitt enthalten. Der app-Service verwendet beispielsweise ein Volume app-data, das nach /data gemountet wird, und ein Netzwerk namens shared-network. Der db-Service verwendet ein Volume namens db-data, das nach /var/lib/postgresql/data gemountet wird.

Alle Volumes und Netzwerke, auf die Services zugreifen können, werden in Block 3 und 4 der Compose-Datei beschrieben. Bevor wir unsere Container ausführen können, müssen wir die beiden Volumes app-data, db-data und unser Netzwerk shared-network einrichten.

# Gemeinsames Netzwerk erstellen, das zur Verbindung der Container verwendet wird
docker network create shared-network

# Volumes für Container erstellen, um Daten zu persistieren
docker volume create app-data
docker volume create db-data

Jetzt, da alles eingerichtet ist, erstellen wir einen Run-Befehl für den ersten Container. In der Compose-Datei siehst du, dass app von db abhängt (depends_on), was bedeutet, dass wir zuerst den db-Container ausführen müssen:

docker run \
-e POSTGRES_PASSWORD=password \ # environment wird zu -e Flags oder --env-file
-v db-data:/var/lib/postgresql/data \ # db-data Volume mounten
--network shared-network \ # Container mit dem gemeinsamen Netzwerk verbinden
-p 5432:5432 \ # Host-Port 5432 auf Container-Port 5432 mappen
-d \ # im Detached-Modus ausführen
postgres

Beachte, dass ich absichtlich nicht alle Einstellungen verwendet habe, die in der obigen docker-compose.yml-Datei beschrieben sind. In diesem Fall habe ich einfach die Option container_name übersprungen. Es wäre möglich, das Flag --name my_db_container zu verwenden, um den Container zu taggen. Ich wollte jedoch zeigen, dass Docker Compose-Setups oft ausgeführt werden können, ohne jede Option zu kopieren. Es ist wichtig, erforderliche Einstellungen von optionalen zu unterscheiden, und je nach Anwendungsfall kannst du möglicherweise auch eine einfachere Version des Compose-Setups ausführen, die für deinen Anwendungsfall ausreicht.

Gleichzeitig habe ich dem Run-Befehl ein neues Flag -d hinzugefügt, das in der Compose-Datei nicht explizit beschrieben ist. Die individuelle Ausführung von Containern gibt dir einige Flexibilität. Du könntest beispielsweise auch Umgebungsvariablen in einer .env-Datei definieren und das Flag --env-file in deinem Run-Befehl verwenden, um darauf zuzugreifen.

Schauen wir uns als nächstes den app-Service an. Der Service enthält einen build-Block in der Compose-Datei. Das bedeutet, dass wir möglicherweise zuerst unser Image erstellen müssen, bevor wir einen Container davon ausführen können.

docker build \
--build-arg APP_ENV=production \ # Build-Zeit-Konfiguration
-t app \ # Image taggen
./app \ # Build-Kontext definieren (Ort, der als Root für nachfolgende Docker-Befehle dient)

Wenn dein Build erfolgreich war, kannst du das App-Image ausführen mit:

docker run -d \
  --name my_app_container \                          # Benutzerdefinierter Container-Name
  -p 8080:80 \                                       # Port-Mapping
  -e APP_ENV=production \                            # Umgebungsvariable
  -e APP_SECRET=mysecret \                           # Weitere Umgebungsvariable
  -v app-data:/data \                                # Volume-Mount für persistente Daten
  --network shared-network \                         # Mit gemeinsamen Netzwerk verbinden
  --restart on-failure \                             # Neustart-Richtlinie
  --label com.example.description="My web app" \     # Benutzerdefiniertes Label
  my-app:latest

Auch hier könntest du diese App mit einer anderen Neustart-Richtlinie oder zum Beispiel ohne das Label zum Laufen bringen.

Die wichtigsten Einstellungen, die du berücksichtigen solltest, wenn du versuchst, ein Compose-Setup zum Laufen zu bringen, sind:

  • Port-Mappings
  • Volume-Mounts
  • Netzwerke und
  • Umgebungsvariablen

Andere Einstellungen sind möglich, aber oft nicht unbedingt erforderlich.

Zusammenfassung

Das Dekonstruieren einer Docker Compose-Datei und das Ausführen von Containern einzeln erfordert die Identifizierung der Services, Netzwerke, Volumes und Umgebungseinstellungen, die in der Compose-Datei definiert sind.

Nachdem du diese Docker-Objekte eingerichtet hast, kannst du die notwendigen Docker Build- und Run-Befehle für jeden Service ableiten.

Während einige Optionen weggelassen werden können, sind Schlüsselelemente wie Port-Mappings, Volume-Mounts und Umgebungsvariablen entscheidend, um das Compose-Setup zu replizieren.

Schau dir Sliplane für eine einfache Möglichkeit an, Docker-Container zu deployen.

Willkommen in der Container-Cloud

Sliplane macht es einfach, Container in der Cloud zu deployen und bei Bedarf zu skalieren. Probier es jetzt aus!