diff --git a/build/Dockerfile b/build/Dockerfile index 3bfc359..5697e62 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -50,22 +50,15 @@ COPY . . # Run composer post-autoload-dump scripts (package discovery etc.) RUN composer run-script post-autoload-dump --no-interaction || true -# Build Vite assets (outputs to public/build/) RUN npm run build -# Copy public/ → public-build/ so the production stage retains built assets -# even after public/ becomes a runtime bind-mount target. -RUN cp -r public/ public-build/ - # ============================================================================= # Stage 2: Production # PHP-FPM runtime image with all system dependencies. -# Node.js is NOT present here. # ============================================================================= FROM php:8.4-fpm-bookworm AS production -# System packages (excluding Node.js — not needed at runtime) RUN apt-get update && apt-get install -y --no-install-recommends \ supervisor \ libzip-dev \ @@ -84,6 +77,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ git \ && rm -rf /var/lib/apt/lists/* +# Node.js 20 LTS — needed at boot to build Vite assets into the bind-mounted public/ +RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ + && apt-get install -y --no-install-recommends nodejs \ + && rm -rf /var/lib/apt/lists/* + # LibreOffice for PowerPoint → PDF conversion (large layer, separate cache) RUN apt-get update && apt-get install -y --no-install-recommends \ libreoffice-impress \ @@ -107,9 +105,6 @@ WORKDIR /app # ── Copy built application from build stage ────────────────────────────────── COPY --from=build /app /app -# Remove node_modules — not needed at runtime -RUN rm -rf /app/node_modules - # ── Install Docker config files ────────────────────────────────────────────── # Supervisord (manages php-fpm, queue:work, schedule:work) COPY build/supervisord.conf /etc/supervisor/conf.d/supervisord.conf @@ -138,8 +133,7 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ cgi-fcgi -bind -connect 127.0.0.1:9000 2>/dev/null | grep -q "pong" || exit 1 # boot-container.sh runs as root: creates dirs, sets permissions, -# creates DB on first run, runs migrations, runs cache commands, -# syncs built assets to the bind-mounted public/ directory, -# then exec's supervisord (CMD). +# creates DB on first run, builds Vite assets, runs migrations, +# warms caches, then exec's supervisord (CMD). ENTRYPOINT ["/app/build/boot-container.sh"] CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/conf.d/supervisord.conf"] diff --git a/build/boot-container.sh b/build/boot-container.sh index db78ba2..d67c57c 100755 --- a/build/boot-container.sh +++ b/build/boot-container.sh @@ -24,18 +24,10 @@ mkdir -p \ chown -R www-data:www-data storage bootstrap/cache database 2>/dev/null || true chmod -R 775 storage bootstrap/cache database 2>/dev/null || true -# Remove Vite dev server hot file if it leaked into the bind-mounted public/ -# (causes Laravel to try localhost:5173 instead of reading the manifest) rm -f /app/public/hot -# Sync built Vite assets from the image (public-build/) into the -# bind-mounted public/ directory. This ensures Caddy always serves -# up-to-date assets even though public/ is a host bind-mount. -if [ -d /app/public-build ]; then - echo "[boot] Syncing built assets to public/..." - cp -r /app/public-build/. /app/public/ - chown -R www-data:www-data /app/public 2>/dev/null || true -fi +echo "[boot] Building Vite assets..." +npm run build # Create the storage symlink after volumes are mounted # (public/storage → storage/app/public)