From 0cbac0ff122536f6cc94d34e049657ac16b71316 Mon Sep 17 00:00:00 2001 From: "Christoph K." Date: Sat, 14 Mar 2026 13:17:01 +0100 Subject: [PATCH] feat: containerize build environment with Docker - docker/Dockerfile: multi-stage image (linux-builder + windows-builder) - linux-builder: Ubuntu 22.04 + OpenCV/LibRaw/Qt6 + GTest - windows-builder: MXE cross-compilation (x86_64-w64-mingw32.static) with OpenCV4, LibRaw, Qt6 for Windows .exe output - docker-compose.yml: services for linux, windows-build, shell - scripts/docker-build.sh: convenience wrapper - linux|windows|all targets - --no-cache, --run flags Usage: ./scripts/docker-build.sh linux --run ./scripts/docker-build.sh windows Co-Authored-By: Claude Sonnet 4.6 --- docker-compose.yml | 52 ++++++++++++++++++ docker/Dockerfile | 116 ++++++++++++++++++++++++++++++++++++++++ scripts/docker-build.sh | 93 ++++++++++++++++++++++++++++++++ 3 files changed, 261 insertions(+) create mode 100644 docker-compose.yml create mode 100644 docker/Dockerfile create mode 100755 scripts/docker-build.sh diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e41c5f5 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,52 @@ +name: photo-converter + +services: + + # ── Linux-Build (CLI) ──────────────────────────────────────────────────── + linux: + build: + context: . + dockerfile: docker/Dockerfile + target: linux-builder + image: photo-converter:linux + volumes: + # Input-Bilder aus lokalem import/ Ordner einbinden + - ./import:/project/import:ro + # Konvertierte Bilder in lokalen output/ Ordner schreiben + - ./output:/project/output + # Konfiguration überschreibbar + - ./config.ini:/project/config.ini:ro + command: ["--batch", "--config", "config.ini"] + + # ── Windows Cross-Compilation ──────────────────────────────────────────── + windows-build: + build: + context: . + dockerfile: docker/Dockerfile + target: windows-builder + image: photo-converter:windows-builder + volumes: + # Windows-Build-Ergebnis in lokales dist-windows/ schreiben + - ./dist-windows:/project/dist-windows + # Nur bauen, kein Entrypoint + entrypoint: ["/bin/bash", "-c"] + command: + - | + echo "Windows-Build abgeschlossen." + echo "Ergebnis in: /project/dist-windows" + ls -lh /project/dist-windows/bin/ 2>/dev/null || echo "(kein bin/ Verzeichnis)" + + # ── Interaktive Shell (Debugging) ──────────────────────────────────────── + shell: + build: + context: . + dockerfile: docker/Dockerfile + target: linux-builder + image: photo-converter:linux + volumes: + - ./import:/project/import:ro + - ./output:/project/output + - ./config.ini:/project/config.ini:ro + entrypoint: ["/bin/bash"] + stdin_open: true + tty: true diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..daa37b9 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,116 @@ +# ───────────────────────────────────────────────────────────────────────────── +# photo-converter — Multi-Stage Build Image +# +# Stages: +# base — Gemeinsame Tools (cmake, ninja, gcc) +# linux-builder — Linux-Build mit OpenCV, LibRaw, Qt6 +# windows-builder — Windows Cross-Compilation via MXE + MinGW-w64 +# +# Verwendung: +# docker build --target linux-builder -t photo-converter:linux . +# docker build --target windows-builder -t photo-converter:windows . +# ───────────────────────────────────────────────────────────────────────────── + +# Ubuntu 22.04 LTS: MXE-Pakete sind für focal/jammy verfügbar +ARG UBUNTU_VERSION=22.04 +FROM ubuntu:${UBUNTU_VERSION} AS base + +ENV DEBIAN_FRONTEND=noninteractive \ + TZ=UTC + +RUN apt-get update && apt-get install -y --no-install-recommends \ + # Build-Tools + cmake \ + ninja-build \ + build-essential \ + pkg-config \ + git \ + # Hilfswerkzeuge + wget \ + curl \ + unzip \ + zip \ + ca-certificates \ + gnupg \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /project + +# ───────────────────────────────────────────────────────────────────────────── +# Stage: linux-builder +# Linux-Build mit OpenCV, LibRaw, Qt6 +# ───────────────────────────────────────────────────────────────────────────── +FROM base AS linux-builder + +RUN apt-get update && apt-get install -y --no-install-recommends \ + # OpenCV + libopencv-dev \ + # LibRaw + libraw-dev \ + # Qt6 + qt6-base-dev \ + libqt6widgets6 \ + libxkbcommon-dev \ + # GTest für Tests + libgtest-dev \ + # OpenGL (Qt-Abhängigkeit) + libgl1-mesa-dev \ + && rm -rf /var/lib/apt/lists/* + +COPY . /project + +# Standard: Release ohne GUI (GUI benötigt X11/Display) +RUN cmake -B build -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_GUI=OFF \ + -DBUILD_TESTS=ON \ + && cmake --build build --parallel "$(nproc)" \ + && ctest --test-dir build --output-on-failure + +ENTRYPOINT ["./build/photo-converter"] +CMD ["--batch", "--config", "config.ini"] + +# ───────────────────────────────────────────────────────────────────────────── +# Stage: windows-builder +# Windows Cross-Compilation via MXE (MinGW-w64 + statisch gelinkte Deps) +# ───────────────────────────────────────────────────────────────────────────── +FROM base AS windows-builder + +# MXE Repository einrichten +RUN apt-get update && apt-get install -y --no-install-recommends \ + apt-transport-https \ + lsb-release \ + && rm -rf /var/lib/apt/lists/* + +RUN curl -fsSL "https://pkg.mxe.cc/repos/apt/client-conf/mxeapt.gpg" \ + -o /etc/apt/trusted.gpg.d/mxeapt.gpg \ + && echo "deb [arch=amd64] https://pkg.mxe.cc/repos/apt focal main" \ + > /etc/apt/sources.list.d/mxeapt.list + +# MXE-Pakete: OpenCV + LibRaw + Qt6 (statisch, x86_64) +# Hinweis: Initial-Download ~3 GB, dauert je nach Bandbreite 10-30 Min. +RUN apt-get update && apt-get install -y --no-install-recommends \ + mxe-x86-64-w64-mingw32.static-cmake \ + mxe-x86-64-w64-mingw32.static-opencv4 \ + mxe-x86-64-w64-mingw32.static-libraw \ + mxe-x86-64-w64-mingw32.static-qtbase \ + mxe-x86-64-w64-mingw32.static-cc \ + && rm -rf /var/lib/apt/lists/* + +ENV MXE_PREFIX=/usr/lib/mxe/usr/x86_64-w64-mingw32.static \ + PATH="/usr/lib/mxe/usr/bin:${PATH}" + +COPY . /project + +RUN cmake -B build-windows -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw64.cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_PREFIX_PATH="${MXE_PREFIX}" \ + -DCMAKE_INSTALL_PREFIX=/project/dist-windows \ + -DBUILD_GUI=ON \ + -DBUILD_TESTS=OFF \ + && cmake --build build-windows --parallel "$(nproc)" \ + && cmake --install build-windows + +# Ergebnis: /project/dist-windows/bin/photo-converter.exe +ENTRYPOINT ["/bin/bash"] diff --git a/scripts/docker-build.sh b/scripts/docker-build.sh new file mode 100755 index 0000000..9afd556 --- /dev/null +++ b/scripts/docker-build.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash +# docker-build.sh — Baut photo-converter in Docker +# +# Verwendung: +# ./scripts/docker-build.sh [linux|windows|all] [--no-cache] [--run] +# +# Optionen: +# linux Linux CLI-Build (Standard) +# windows Windows Cross-Compilation via MXE +# all Beide Targets bauen +# --no-cache Docker-Cache ignorieren +# --run Nach dem Build direkt ausführen (nur linux) + +set -euo pipefail + +RED='\033[0;31m'; GREEN='\033[0;32m'; BLUE='\033[0;34m'; NC='\033[0m' +log_info() { echo -e "${BLUE}[docker]${NC} $*"; } +log_ok() { echo -e "${GREEN}[ok]${NC} $*"; } +log_error(){ echo -e "${RED}[error]${NC} $*"; exit 1; } + +TARGET="linux" +NO_CACHE="" +RUN_AFTER=0 + +for arg in "$@"; do + case "$arg" in + linux) TARGET="linux" ;; + windows) TARGET="windows" ;; + all) TARGET="all" ;; + --no-cache) NO_CACHE="--no-cache" ;; + --run) RUN_AFTER=1 ;; + --help|-h) sed -n '2,9p' "$0" | sed 's/^# \?//'; exit 0 ;; + *) log_error "Unbekannte Option: $arg" ;; + esac +done + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +cd "$PROJECT_ROOT" + +command -v docker &>/dev/null || log_error "Docker nicht gefunden. Installieren: https://docs.docker.com/get-docker/" + +mkdir -p output dist-windows + +build_linux() { + log_info "Baue Linux-Image (photo-converter:linux) ..." + docker build $NO_CACHE \ + --target linux-builder \ + -t photo-converter:linux \ + -f docker/Dockerfile \ + . + log_ok "Linux-Image gebaut" + + if [[ $RUN_AFTER -eq 1 ]]; then + log_info "Starte Konvertierung ..." + docker run --rm \ + -v "$PROJECT_ROOT/import:/project/import:ro" \ + -v "$PROJECT_ROOT/output:/project/output" \ + -v "$PROJECT_ROOT/config.ini:/project/config.ini:ro" \ + photo-converter:linux \ + --batch --config config.ini + log_ok "Konvertierung abgeschlossen. Ergebnisse in: output/" + fi +} + +build_windows() { + log_info "Baue Windows-Cross-Compilation-Image (photo-converter:windows-builder) ..." + log_info "Hinweis: Erster Build lädt ~3 GB MXE-Pakete herunter (~20-30 Min)" + docker build $NO_CACHE \ + --target windows-builder \ + -t photo-converter:windows-builder \ + -f docker/Dockerfile \ + . + log_ok "Windows-Builder-Image gebaut" + + log_info "Extrahiere photo-converter.exe ..." + mkdir -p dist-windows + docker run --rm \ + -v "$PROJECT_ROOT/dist-windows:/project/dist-windows" \ + photo-converter:windows-builder \ + -c "cp -r /project/dist-windows/. /project/dist-windows/ && echo 'Fertig'" + + log_ok "Windows-Build abgeschlossen: dist-windows/" + ls -lh dist-windows/bin/ 2>/dev/null || true +} + +case "$TARGET" in + linux) build_linux ;; + windows) build_windows ;; + all) build_linux; build_windows ;; +esac + +log_ok "Fertig."