# syntax=docker/dockerfile:1 ARG PHP_VERSION=8.4 FROM composer:2 AS composer WORKDIR /app COPY composer.json composer.lock ./ RUN composer install \ --no-dev \ --prefer-dist \ --no-interaction \ --no-scripts \ --classmap-authoritative \ --ignore-platform-req=ext-intl COPY . . RUN mkdir -p bootstrap/cache storage/framework/cache storage/framework/sessions storage/framework/views storage/logs \ && composer dump-autoload --optimize --classmap-authoritative --no-scripts FROM node:22-bookworm-slim AS frontend WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY vite.config.js ./ COPY resources ./resources COPY public ./public # resources/css/filament/admin/theme.css imports Filament's own uncompiled CSS, # so the Vite build needs those files present. Only Filament's subtree is copied # rather than all of vendor/, to keep this stage's context small. COPY --from=composer /app/vendor/filament ./vendor/filament RUN npm run build FROM dunglas/frankenphp:1-php${PHP_VERSION}-bookworm AS runtime RUN install-php-extensions \ intl \ mbstring \ pdo_pgsql \ zip \ opcache \ pcntl \ bcmath \ sodium \ gd RUN useradd --create-home --shell /usr/sbin/nologin --uid 1000 appuser WORKDIR /app COPY --from=composer --chown=appuser:appuser /app /app COPY --from=frontend --chown=appuser:appuser /app/public/build /app/public/build COPY docker/Caddyfile /etc/caddy/Caddyfile RUN mkdir -p storage/framework/cache storage/framework/sessions storage/framework/views storage/logs bootstrap/cache \ && chown -R appuser:appuser storage bootstrap/cache COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh USER appuser EXPOSE 8000 HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \ CMD curl -fsS http://127.0.0.1:8000/up || exit 1 ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] CMD ["frankenphp", "run", "--config", "/etc/caddy/Caddyfile"]