# ============================================================================= # CTmine-client · ContainerMine Client # Multi-Stage Dockerfile: # Stage 1 (web-build): baut das Vue 3 + Vite Dashboard # Stage 2 (final): Ubuntu mit Xvfb/x11vnc/websockify/openbox/nginx, # Prism Launcher, echtem Minecraft-Client, Node-API # ============================================================================= # ---------------------------------------------------------------------------- # Stage 1: Vue Dashboard bauen # ---------------------------------------------------------------------------- FROM node:22-slim AS web-build WORKDIR /build # Erst nur Abhängigkeiten (besserer Layer-Cache). COPY web/package.json web/package-lock.json* ./ RUN npm install --no-audit --no-fund # Quellen kopieren und Produktions-Build erstellen. COPY web/ ./ RUN npm run build # ---------------------------------------------------------------------------- # Stage 2: Runtime # ---------------------------------------------------------------------------- FROM ubuntu:24.04 ENV DEBIAN_FRONTEND=noninteractive \ TZ=Europe/Berlin \ DISPLAY=:0 \ CONFIG_DIR=/config \ PRISM_DIR=/config/prism \ WEB_ROOT=/var/www/ctmine \ MC_API_PORT=3000 \ PUID=1000 \ PGID=1000 # --- Systempakete ---------------------------------------------------------- # Xvfb virtuelles Display # x11vnc VNC-Server auf Xvfb # websockify VNC → WebSocket für noVNC # novnc Browser-VNC-Client (wird hier nur als Fallback gehostet) # openbox leichter Windowmanager (sonst kein Fokus/Rahmen für MC) # nginx liefert Dashboard + proxyt API/Websockify # nodejs Status-API # supervisord Prozess-Manager # gosu Prozess als Runtime-Benutzer starten # xdpyinfo Auflösung auslesen (für /api/status) # Prism Launcher benötigt Qt6 + multimediale Libs. RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ wget \ gnupg \ xz-utils \ \ xvfb \ x11vnc \ python3 \ python3-websockify \ novnc \ openbox \ nginx \ supervisor \ gosu \ x11-utils \ \ nodejs \ \ qt6-base-dev \ qt6-wayland \ libqt6core6 \ libqt6gui6 \ libqt6network6 \ libqt6widgets6 \ libqt6svg6 \ libqt6opengl6 \ libqt6multimedia6 \ libgl1 \ libglx-mesa0 \ libegl1 \ libegl-mesa0 \ mesa-utils \ libopenal1 \ libpulse0 \ libglfw3 \ libflac12 \ libvorbisfile3 \ libopengl0 \ locales \ tzdata \ && rm -rf /var/lib/apt/lists/* # Locale generieren (Qt verlangt ein funktionierendes utf8-Locale). RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen ENV LANG=en_US.UTF-8 \ LANGUAGE=en_US:en \ LC_ALL=en_US.UTF-8 # --- Runtime-Benutzer (UID/GID 1000) --------------------------------------- # Ubuntu hat bereits eine Gruppe/einen User mit ID 1000 (»ubuntu«). Wir nutzen # diese, statt sie neu anzulegen: bestehende Gruppe/User werden umbenannt. RUN if getent group 1000 >/dev/null; then \ existing_group=$(getent group 1000 | cut -d: -f1) && \ groupmod -n ctmine "$existing_group"; \ else \ groupadd -g 1000 ctmine; \ fi && \ if getent passwd 1000 >/dev/null; then \ existing_user=$(getent passwd 1000 | cut -d: -f1) && \ usermod -l ctmine -d /home/ctmine -m -s /bin/bash "$existing_user" && \ usermod -g 1000 ctmine; \ else \ useradd -m -u 1000 -g 1000 -s /bin/bash ctmine; \ fi && \ mkdir -p /config /var/www/ctmine /app/mc-api && \ chown -R ctmine:ctmine /config /app # --- Prism Launcher installieren ------------------------------------------- # Wir laden den offiziellen portable Linux-Build (Qt6) herunter. Prism ist # eine portable Qt-App — kein systemweites Installieren nötig. Das Archiv # entpackt *flach* (Dateien liegen direkt im Root, kein Unterverzeichnis). ARG PRISM_VERSION=11.0.3 RUN mkdir -p /opt/prism && cd /opt/prism && \ wget -q "https://github.com/PrismLauncher/PrismLauncher/releases/download/${PRISM_VERSION}/PrismLauncher-Linux-Qt6-Portable-${PRISM_VERSION}.tar.gz" -O prism.tar.gz && \ tar -xzf prism.tar.gz && \ rm prism.tar.gz && \ chmod +x /opt/prism/PrismLauncher /opt/prism/bin/prismlauncher # --- Vue-Dashboard aus Stage 1 übernehmen ---------------------------------- COPY --from=web-build /build/dist/ /var/www/ctmine/ # --- Node-API übernehmen --------------------------------------------------- COPY docker/mc-api/ /app/mc-api/ # --- Docker-Konfigurationsdateien ------------------------------------------ COPY docker/supervisor.conf /etc/supervisor/conf.d/supervisord.conf COPY docker/nginx.conf /etc/nginx/nginx.conf COPY docker/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh /opt/prism/PrismLauncher # --- Prism beim ersten Start ins Volume entpacken -------------------------- # So liegen Accounts, Instanzen und Launcher persistent in /config und # überstehen Container-Neustarts. Prism erwartet $HOME als Datenverzeichnis. RUN echo '#!/usr/bin/env bash' > /opt/bootstrap-prism.sh && \ echo 'set -e' >> /opt/bootstrap-prism.sh && \ echo 'if [ ! -x "${PRISM_DIR}/PrismLauncher" ]; then' >> /opt/bootstrap-prism.sh && \ echo ' mkdir -p "${PRISM_DIR}"' >> /opt/bootstrap-prism.sh && \ echo ' cp -r /opt/prism/* "${PRISM_DIR}/"' >> /opt/bootstrap-prism.sh && \ echo ' chmod +x "${PRISM_DIR}/PrismLauncher"' >> /opt/bootstrap-prism.sh && \ echo ' chown -R ctmine:ctmine "${PRISM_DIR}"' >> /opt/bootstrap-prism.sh && \ echo 'fi' >> /opt/bootstrap-prism.sh && \ chmod +x /opt/bootstrap-prism.sh # Volumes: persistente Daten (Accounts, Instanzen, .minecraft). VOLUME ["/config"] EXPOSE 8080 # Healthcheck: ist das Dashboard erreichbar? HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \ CMD wget -qO- http://127.0.0.1:8080/ >/dev/null 2>&1 || exit 1 ENTRYPOINT ["/entrypoint.sh"]