Docker und C++: Containerisierung von Anwendungen für Entwickler

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Docker und C++: Containerisierung von Anwendungen



In der modernen Softwareentwicklung ist die Containerisierung zum De-facto-Standard für die Bereitstellung und Skalierung von Anwendungen geworden. Docker ermöglicht es, eine Anwendung zusammen mit all ihren Abhängigkeiten, Bibliotheken und Konfigurationen in einen isolierten Container zu packen. Für C++-Entwickler ist dies besonders relevant, da C++-Anwendungen oft spezifische Compiler-Versionen, Systembibliotheken und komplexe Build-Prozesse erfordern. In diesem Artikel werden wir erläutern, wie man C++-Anwendungen effektiv mit Docker containerisiert.



Warum Docker für C++?



C++-Anwendungen gelten traditionell als schwierig bereitzustellen, aufgrund von Problemen mit der Portabilität von Binärdateien zwischen verschiedenen Linux-Distributionen. Docker löst dieses Problem, indem es eine einheitliche Laufzeitumgebung bereitstellt. Die Hauptvorteile der Verwendung von Docker für C++-Projekte sind:



  • Reproduzierbarkeit von Builds – Feste Versionen von Compilern und Bibliotheken stellen sicher, dass der Code auf jeder Maschine gleich gebaut wird.
  • Isolation von Abhängigkeiten – Verschiedene Projekte können unterschiedliche Versionen derselben Bibliothek ohne Konflikte verwenden.
  • Vereinfachung von CI/CD – Der Container kann als einheitliches Artefakt für Tests und Deployment verwendet werden.
  • Reduzierung der Größe – Multi-Stage-Builds ermöglichen die Erstellung minimaler Images, die nur die ausführbare Datei enthalten.


Erstellen eines Dockerfile für eine C++-Anwendung



Betrachten wir ein grundlegendes Beispiel. Wir haben eine einfache C++-Anwendung, die "Hello, Docker!" ausgibt.



Quellcode



// main.cpp#include <iostream>

int main() { std::cout << "Hello, Docker!" << std::endl; return 0;}


Basis-Dockerfile



Erstellen wir ein einfaches Dockerfile, das das gcc-Image zum Bauen und Ausführen verwendet:



# Verwende das offizielle GCC-ImageFROM gcc:latest

# Lege das Arbeitsverzeichnis festWORKDIR /app

# Kopiere den QuellcodeCOPY main.cpp .

# Baue die AnwendungRUN g++ -o hello main.cpp

# Führe die Anwendung ausCMD ["./hello"]


Baue und starte den Container:



docker build -t cpp-hello .docker run cpp-hello


Ausgabe: Hello, Docker!



Multi-Stage-Build: Optimierung der Image-Größe



Das Problem des Basis-Ansatzes ist, dass das finale Image den Compiler, Header-Dateien und andere Werkzeuge enthält, die zur Laufzeit nicht benötigt werden. Für eine Production-Umgebung ist dies überflüssig. Die Lösung ist ein Multi-Stage-Build, der es ermöglicht, die Build-Phase von der Ausführungsphase zu trennen.



Optimiertes Dockerfile



# Build-PhaseFROM gcc:latest AS builder

WORKDIR /appCOPY main.cpp .RUN g++ -static -o hello main.cpp

# Finale PhaseFROM alpine:latest

WORKDIR /appCOPY --from=builder /app/hello .

CMD ["./hello"]


In diesem Beispiel verwenden wir statisches Linken (-static), damit die ausführbare Datei nicht von dynamischen Bibliotheken abhängt. Das finale Image belegt nur etwa 5 MB anstelle von 1,2 GB für das Image mit GCC.



Containerisierung eines Projekts mit CMake und Abhängigkeiten



Reale Projekte verwenden normalerweise Build-Systeme (CMake) und externe Abhängigkeiten. Betrachten wir ein Beispiel mit der Bibliothek nlohmann/json.



Projektstruktur



project/├── CMakeLists.txt├── main.cpp├── external/│   └── json.hpp└── Dockerfile


CMakeLists.txt



cmake_minimum_required(VERSION 3.10)project(JsonApp)

set(CMAKE_CXX_STANDARD 17)

add_executable(app main.cpp)target_include_directories(app PRIVATE external)


main.cpp



#include <iostream>#include "json.hpp"

using json = nlohmann::json;

int main() { json data = {{"name"

Blogs

Buchempfehlungen