From 90a5ab74ff70a5b746ea14111e115ad4cc3b6b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Thu, 16 Jul 2026 23:51:02 +0200 Subject: [PATCH] Added docker environment emulating a manual installed Part-DB on debian Used to debug issues like #1423 --- .docker/debian-manual-guide/Dockerfile | 61 +++++++++++++++++++ .../debian-manual-guide/docker-compose.yml | 41 +++++++++++++ .docker/debian-manual-guide/entrypoint.sh | 48 +++++++++++++++ .docker/debian-manual-guide/env.local | 11 ++++ .docker/debian-manual-guide/partdb.conf | 15 +++++ 5 files changed, 176 insertions(+) create mode 100644 .docker/debian-manual-guide/Dockerfile create mode 100644 .docker/debian-manual-guide/docker-compose.yml create mode 100644 .docker/debian-manual-guide/entrypoint.sh create mode 100644 .docker/debian-manual-guide/env.local create mode 100644 .docker/debian-manual-guide/partdb.conf diff --git a/.docker/debian-manual-guide/Dockerfile b/.docker/debian-manual-guide/Dockerfile new file mode 100644 index 00000000..73d0cee9 --- /dev/null +++ b/.docker/debian-manual-guide/Dockerfile @@ -0,0 +1,61 @@ +# Reproduces https://docs.part-db.de/installation/installation_guide-debian.html +# on Debian 12 (bookworm) as closely as possible, for debugging issues reported +# by users who followed that guide (Apache2 + mod_php, not the project's own +# FrankenPHP-based Dockerfile at the repo root). +FROM debian:12 + +ARG HOST_UID=1000 +ARG HOST_GID=1000 + +ENV DEBIAN_FRONTEND=noninteractive + +# --- Prerequisites (guide: "Prerequisites Installation") --- +RUN apt-get update && apt-get upgrade -y && \ + apt-get install -y --no-install-recommends \ + git curl zip ca-certificates software-properties-common \ + apt-transport-https lsb-release nano wget sqlite3 gnupg openssl \ + && rm -rf /var/lib/apt/lists/* + +# --- PHP and Apache2 (guide: "PHP and Apache2 Setup") --- +# Debian 12 ships PHP 8.2 by default, so no extra PHP repo is needed. +RUN apt-get update && apt-get install -y --no-install-recommends \ + apache2 php8.2 libapache2-mod-php8.2 \ + php8.2-opcache php8.2-curl php8.2-gd php8.2-mbstring \ + php8.2-xml php8.2-bcmath php8.2-intl php8.2-zip php8.2-xsl \ + php8.2-sqlite3 php8.2-mysql \ + && rm -rf /var/lib/apt/lists/* + +# --- Composer (guide: "Composer Installation") --- +RUN wget -O /tmp/composer-setup.php https://getcomposer.org/installer \ + && php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer \ + && chmod +x /usr/local/bin/composer \ + && rm /tmp/composer-setup.php + +# --- Node.js and Yarn (guide: "Node.js and Yarn Setup") --- +RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ + && apt-get install -y --no-install-recommends nodejs \ + && curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor -o /usr/share/keyrings/yarnkey.gpg \ + && echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" > /etc/apt/sources.list.d/yarn.list \ + && apt-get update && apt-get install -y --no-install-recommends yarn \ + && rm -rf /var/lib/apt/lists/* + +# Map www-data to the host user's uid/gid so files created inside the +# bind-mounted repo (composer/yarn artifacts, chown'd dirs) don't end up +# owned by a foreign uid on the host. +RUN groupmod -g ${HOST_GID} www-data && usermod -u ${HOST_UID} -g ${HOST_GID} www-data \ + && mkdir -p /var/www/partdb && chown -R www-data:www-data /var/www + +# --- Apache2 Configuration (guide: "Apache2 Configuration") --- +COPY partdb.conf /etc/apache2/sites-available/partdb.conf +RUN ln -sf /etc/apache2/sites-available/partdb.conf /etc/apache2/sites-enabled/partdb.conf \ + && a2enmod rewrite headers access_compat \ + && rm -f /etc/apache2/sites-enabled/000-default.conf + +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +WORKDIR /var/www/partdb +EXPOSE 80 + +ENTRYPOINT ["/entrypoint.sh"] +CMD ["apache2ctl", "-D", "FOREGROUND"] diff --git a/.docker/debian-manual-guide/docker-compose.yml b/.docker/debian-manual-guide/docker-compose.yml new file mode 100644 index 00000000..efe47d00 --- /dev/null +++ b/.docker/debian-manual-guide/docker-compose.yml @@ -0,0 +1,41 @@ +# Reproduces a Debian 12 install following +# https://docs.part-db.de/installation/installation_guide-debian.html +# using the repo checkout two levels up, for debugging. +# +# Usage (from this directory): +# HOST_UID=$(id -u) HOST_GID=$(id -g) docker compose up --build +# +# Then open http://localhost:8080 (login: admin / password printed in the +# container logs by doctrine:migrations:migrate on first run). +# +# vendor/, node_modules/, var/, public/build, public/media and uploads live +# in named volumes so composer/yarn/console never write into the host's own +# working copy - only src/, config/, templates/, assets/, migrations/, etc. +# are shared live for debugging. +services: + partdb: + build: + context: . + args: + HOST_UID: ${HOST_UID:-1000} + HOST_GID: ${HOST_GID:-1000} + container_name: partdb-debian-guide + ports: + - "8080:80" + volumes: + - ../..:/var/www/partdb + - ./env.local:/var/www/partdb/.env.local:ro + - partdb_vendor:/var/www/partdb/vendor + - partdb_node_modules:/var/www/partdb/node_modules + - partdb_var:/var/www/partdb/var + - partdb_public_build:/var/www/partdb/public/build + - partdb_public_media:/var/www/partdb/public/media + - partdb_uploads:/var/www/partdb/uploads + +volumes: + partdb_vendor: + partdb_node_modules: + partdb_var: + partdb_public_build: + partdb_public_media: + partdb_uploads: diff --git a/.docker/debian-manual-guide/entrypoint.sh b/.docker/debian-manual-guide/entrypoint.sh new file mode 100644 index 00000000..b085f7c1 --- /dev/null +++ b/.docker/debian-manual-guide/entrypoint.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# Reproduces the app-setup steps from +# https://docs.part-db.de/installation/installation_guide-debian.html +# against the repo bind-mounted at /var/www/partdb. +set -euo pipefail + +cd /var/www/partdb + +# Only chown the named-volume mount points (see docker-compose.yml) - they're +# fresh docker volumes owned by root until first use. The bind-mounted source +# tree doesn't need it (www-data's uid/gid is mapped to the host user's at +# image build time, so ownership already matches), and recursing into it +# would also try (and fail) to chown the read-only .env.local mount. +chown -R www-data:www-data \ + var vendor node_modules public/build public/media uploads + +as_www() { + # -p preserves the environment (APP_ENV/APP_SECRET/DATABASE_URL from + # docker-compose) across the user switch. Plain `su` resets it, which + # would silently fall back to whatever's baked into .env.local. + su -p -s /bin/bash www-data -c "$*" +} + +if [ ! -f vendor/autoload.php ] || [ "${FORCE_REINSTALL:-0}" = "1" ]; then + echo "==> composer install -o" + as_www "composer install -o" +fi + +if [ ! -d node_modules/.bin ] || [ "${FORCE_REINSTALL:-0}" = "1" ]; then + echo "==> yarn install" + as_www "yarn install" +fi + +if [ ! -f public/build/manifest.json ] || [ "${FORCE_REINSTALL:-0}" = "1" ]; then + echo "==> yarn build" + as_www "yarn build" +fi + +echo "==> cache:clear" +as_www "php bin/console cache:clear" + +echo "==> partdb:check-requirements" +as_www "php bin/console partdb:check-requirements" || true + +echo "==> doctrine:migrations:migrate" +as_www "php bin/console doctrine:migrations:migrate --no-interaction" + +exec "$@" diff --git a/.docker/debian-manual-guide/env.local b/.docker/debian-manual-guide/env.local new file mode 100644 index 00000000..61545710 --- /dev/null +++ b/.docker/debian-manual-guide/env.local @@ -0,0 +1,11 @@ +# Bind-mounted over /var/www/partdb/.env.local inside the container only. +# The host's real .env.local (dev, MySQL on 127.0.0.1) is never touched or +# read - this guarantees APP_ENV/DATABASE_URL are correct for BOTH Apache/ +# mod_php web requests and CLI (console/composer) commands, without relying +# on environment variables being propagated into Apache's subprocess env +# (which is what caused the "WebProfilerBundle" dev-bundle error: web +# requests were silently falling back to the host .env.local's APP_ENV=dev, +# while --no-dev composer install never installed that bundle). +APP_ENV=prod +APP_SECRET=0000000000000000000000000000000000000000000000000000000000debug +DATABASE_URL="sqlite:///%kernel.project_dir%/var/app.db" diff --git a/.docker/debian-manual-guide/partdb.conf b/.docker/debian-manual-guide/partdb.conf new file mode 100644 index 00000000..8e53b236 --- /dev/null +++ b/.docker/debian-manual-guide/partdb.conf @@ -0,0 +1,15 @@ +# Verbatim from https://docs.part-db.de/installation/installation_guide-debian.html + + ServerName partdb.lan + ServerAlias www.partdb.lan + + DocumentRoot /var/www/partdb/public + + AllowOverride All + Order Allow,Deny + Allow from All + + + ErrorLog /var/log/apache2/partdb_error.log + CustomLog /var/log/apache2/partdb_access.log combined +