diff --git a/Dockerfile b/Dockerfile index f4dc6e7..452568e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,21 +1,22 @@ # syntax=docker/dockerfile:1.6 +ARG PHP_VERSION=8.3 +ARG NODE_VERSION=20 + ############################ # Stage 1: PHP (Composer) # ############################ -FROM php:8.4-fpm-alpine AS phpbuild +FROM php:${PHP_VERSION}-fpm-alpine AS composer_build -# Build deps for PHP extensions + composer +# OS deps for building PHP extensions that Composer plugins may need RUN set -eux; \ - apk add --no-cache \ - git unzip \ - libzip-dev oniguruma-dev icu-dev \ - autoconf build-base postgresql-dev + apk add --no-cache git unzip icu-dev libzip-dev oniguruma-dev postgresql-dev autoconf build-base -# PHP extensions (PG + MySQL + zip/opcache/intl) -RUN docker-php-ext-configure zip; \ +# PHP extensions required by Laravel (build here too if scripts need them) +RUN set -eux; \ + docker-php-ext-configure zip; \ docker-php-ext-install -j"$(nproc)" \ - pdo_mysql pdo_pgsql pgsql zip opcache intl + pdo_mysql pdo_pgsql pgsql zip intl mbstring bcmath opcache # Composer ENV COMPOSER_ALLOW_SUPERUSER=1 COMPOSER_HOME=/tmp/composer @@ -24,51 +25,58 @@ COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer WORKDIR /app # Install PHP deps first for better layer caching COPY composer.json composer.lock ./ -RUN composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader --no-scripts +# DO NOT skip scripts — Laravel needs them (package discovery, etc.) +RUN composer install \ + --no-dev --no-interaction --prefer-dist \ + --optimize-autoloader -# Copy full app source (now vendor/ exists for later stages) +# Bring in the rest of the app COPY . . ############################ # Stage 2: Frontend (Vite) # ############################ -FROM node:20-alpine AS nodebuild +FROM node:${NODE_VERSION}-alpine AS node_build WORKDIR /app -# Bring in the **already-composed** app (includes vendor/) -COPY --from=phpbuild /app /app +# Only the files Node needs (faster context & cache) +COPY package.json package-lock.json* pnpm-lock.yaml* yarn.lock* vite.config.* ./ +COPY resources ./resources +COPY public ./public +# If your Vite config imports from `resources` only, this is enough. +# If you reference other paths at build time, copy them similarly. -# Native build tools in case any npm deps need them +# Native build deps (rarely needed, but safe) RUN apk add --no-cache python3 make g++ -# JS deps & build (Laravel default expects package.json at repo root) -RUN if [ -f package-lock.json ]; then npm ci; \ - elif [ -f pnpm-lock.yaml ]; then corepack enable && pnpm i --frozen-lockfile; \ - elif [ -f yarn.lock ]; then yarn install --frozen-lockfile; \ +# Install using the appropriate lockfile +RUN set -eux; \ + if [ -f pnpm-lock.yaml ]; then corepack enable && pnpm i --frozen-lockfile; \ + elif [ -f yarn.lock ]; then corepack enable && yarn install --frozen-lockfile; \ + elif [ -f package-lock.json ]; then npm ci; \ else npm i; fi ENV NODE_ENV=production -# Standard Laravel: "build": "vite build" +# Standard Laravel vite build => outputs to public/build + manifest.json RUN npm run build ##################################### # Stage 3: Runtime (nginx + php-fpm)# ##################################### -FROM php:8.4-fpm-alpine +FROM php:${PHP_VERSION}-fpm-alpine # Base runtime packages RUN set -eux; \ - apk add --no-cache \ - nginx supervisor curl \ - libzip icu-libs + apk add --no-cache nginx supervisor curl libzip icu-libs oniguruma libpq -# Build PHP runtime extensions and install libpq (needed by pdo_pgsql/pgsql) +# Build required PHP extensions in the final image (so they exist at runtime) RUN set -eux; \ - apk add --no-cache libzip-dev icu-dev oniguruma-dev postgresql-dev; \ + apk add --no-cache libzip-dev icu-dev oniguruma-dev postgresql-dev autoconf build-base; \ docker-php-ext-configure zip; \ - docker-php-ext-install -j"$(nproc)" pdo_mysql pdo_pgsql pgsql zip opcache intl; \ - apk add --no-cache libpq; \ - apk del --no-progress --purge libzip-dev icu-dev oniguruma-dev postgresql-dev || true + docker-php-ext-install -j"$(nproc)" \ + pdo_mysql pdo_pgsql pgsql zip intl mbstring bcmath opcache; \ + # Slim back down + apk del --no-progress --purge libzip-dev icu-dev oniguruma-dev postgresql-dev autoconf build-base || true # php.ini production + opcache tuning RUN set -eux; \ @@ -76,8 +84,8 @@ RUN set -eux; \ { \ echo "opcache.enable=1"; \ echo "opcache.enable_cli=0"; \ - echo "opcache.memory_consumption=128"; \ - echo "opcache.max_accelerated_files=20000"; \ + echo "opcache.memory_consumption=192"; \ + echo "opcache.max_accelerated_files=40000"; \ echo "opcache.validate_timestamps=0"; \ echo "realpath_cache_size=4096K"; \ echo "realpath_cache_ttl=600"; \ @@ -91,7 +99,7 @@ RUN set -eux; \ sed -ri 's|^group\s*=.*|group = nginx|g' /usr/local/etc/php-fpm.d/www.conf; \ { echo "ping.path = /ping"; echo "pm.status_path = /status"; echo "catch_workers_output = yes"; } >> /usr/local/etc/php-fpm.d/www.conf -# Directories +# Runtime dirs RUN set -eux; \ mkdir -p /run/nginx /var/log/nginx /var/log/supervisor \ /etc/nginx/conf.d /var/www/html \ @@ -99,13 +107,13 @@ RUN set -eux; \ WORKDIR /var/www/html -# App code from composer stage -COPY --from=phpbuild --chown=nginx:nginx /app /var/www/html +# Copy application code (without node_modules) and vendor from composer stage +COPY --from=composer_build --chown=nginx:nginx /app /var/www/html -# Built frontend assets from node stage (public/build/** including manifest.json) -COPY --from=nodebuild --chown=nginx:nginx /app/public/build /var/www/html/public/build +# Copy built frontend assets (public/build with manifest.json) +COPY --from=node_build --chown=nginx:nginx /app/public/build /var/www/html/public/build -# Nginx + Supervisor configs + health + entrypoint (must exist in your repo) +# Nginx + Supervisor configs + health + entrypoint (these must exist in your repo) COPY ./docker/nginx.conf /etc/nginx/nginx.conf COPY ./docker/site.conf /etc/nginx/conf.d/default.conf COPY ./docker/supervisord.conf /etc/supervisord.conf @@ -125,7 +133,7 @@ RUN set -eux; \ /var/cache/nginx /var/lib/nginx /run/nginx /var/log/nginx /var/log/supervisor; \ chmod -R ug+rwX storage bootstrap/cache -# Env + port +# Environment + port (ensure site.conf listens on 8080 or change EXPOSE to 80) ENV APP_ENV=production APP_DEBUG=false APP_URL=http://localhost APP_PORT=8080 EXPOSE 8080