Docker und C++: Fortgeschrittene Containerisierung von Anwendungen

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 auf fortgeschrittenem Niveau



Die Containerisierung von C++-Anwendungen mit Docker ist nicht einfach nur das Verschieben von Code in eine isolierte Umgebung. Auf fortgeschrittenem Niveau ist es die Kunst, zwischen Image-Größe, Build-Geschwindigkeit, Sicherheit und Kompatibilität mit Systembibliotheken zu balancieren. In diesem Artikel werden wir Techniken besprechen, die Ihnen helfen, effiziente, leichte und wartbare Docker-Images für C++-Projekte zu erstellen.



Wir gehen davon aus, dass Sie bereits mit den Grundlagen von Docker vertraut sind (Befehle docker build, docker run) und die grundlegende Syntax von Dockerfile kennen. Nun wenden wir uns den realen Aufgaben zu: Multi-Stage-Builds, Arbeit mit Systemabhängigkeiten, Debugging innerhalb des Containers und Integration in CI/CD.



1. Multi-Stage-Build: Kompilierung und Ausführung trennen



Das Hauptproblem von C++ in Docker ist die Image-Größe. Ein vollständiger Werkzeugsatz (g++, cmake, make, dev-Pakete) kann 1–2 GB wiegen. Die Lösung ist der Multi-Stage-Build.



Betrachten wir ein klassisches Beispiel: eine C++-Anwendung, die die Bibliothek libcurl verwendet.



# Erste Stufe: BuildFROM ubuntu:22.04 AS builder

RUN apt-get update && apt-get install -y \ build-essential \ cmake \ libcurl4-openssl-dev \ && rm -rf /var/lib/apt/lists/*

WORKDIR /appCOPY . .

RUN cmake -B build -DCMAKE_BUILD_TYPE=Release \ && cmake --build build --parallel $(nproc)

# Zweite Stufe: Ausführbares ImageFROM ubuntu:22.04-slim

RUN apt-get update && apt-get install -y \ libcurl4 \ && rm -rf /var/lib/apt/lists/*

COPY --from=builder /app/build/myapp /usr/local/bin/myapp

CMD ["myapp"]


Wichtige Punkte:

  • In der ersten Stufe (builder) installieren wir alle Werkzeuge und Abhängigkeiten für den Build.
  • In der zweiten Stufe – nur die Laufzeitabhängigkeiten (libcurl4 anstelle von libcurl4-openssl-dev).
  • Das finale Image enthält nur die kompilierte Binärdatei und die notwendigen Bibliotheken.
  • Wir verwenden --parallel $(nproc), um den Build zu beschleunigen.


Die Image-Größe reduziert sich von ~1,2 GB auf ~80 MB. Dies ist kritisch für das Deployment und das Herunterladen von Images in CI/CD.



2. Optimierung des Cachings und der Docker-Layer



Jede Anweisung in einer Dockerfile erzeugt einen Layer. Eine falsche Reihenfolge der Anweisungen führt dazu, dass bei der geringsten Codeänderung der gesamte Cache zurückgesetzt wird.



Regel: Zuerst das kopieren, was sich selten ändert (CMakeLists.txt, Abhängigkeiten), dann den Code.



FROM ubuntu:22.04 AS builder

WORKDIR /app

# 1. Systemabhängigkeiten (ändern sich selten)RUN apt-get update && apt-get install -y \ build-essential cmake libboost-all-dev \ && rm -rf /var/lib/apt/lists/*

# 2. Build-Konfigurationsdateien (ändern sich nicht oft)COPY CMakeLists.txt .

# 3. Quellcode (ändert sich ständig)COPY src/ ./src/

# 4. BuildRUN cmake -B build && cmake --build build


Zusätzliche Tipps:

  • Verwenden Sie .dockerignore, um build/, .git/, *.o auszuschließen.
  • Gruppieren Sie RUN apt-get install in einen Befehl – dies reduziert die Anzahl der Layer.
  • Für C++-Projekte mit vielen Header-Dateien ziehen Sie ccache innerhalb des Containers in Betracht.


3. Arbeit mit Systembibliotheken und statisches Linken



Manchmal fehlen dynamische Bibliotheken im Container oder sind inkompatibel. Ein fortgeschrittener Ansatz ist das statische Linken oder die Verwendung von Alpine Linux.



Variante A: Statischer Build (g++)

FROM alpine:3.18 AS builder

RUN apk add --no-cache g++ gcc musl-dev make cmake

WORKDIR /appCOPY . .

# Statisches LinkenRUN g++ -static -O2 -o myapp main.cpp -lpthread

FROM scratchCO

Blogs

Buchempfehlungen