Laravel 13 + Filament 5 admin panel and REST API for a non-profit developer collective, backed by the Pireon OAuth identity server. The public site is a separate, server-rendered application consuming /api/public/v1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
123 lines
4.2 KiB
Docker
123 lines
4.2 KiB
Docker
# syntax=docker/dockerfile:1
|
|
|
|
###############################################################################
|
|
# Base
|
|
#
|
|
# Both stages share it, so dependencies are resolved against exactly the PHP
|
|
# that will run them — Filament requires ext-intl, and a composer image that
|
|
# lacks it would either refuse to install or, worse, install something the
|
|
# runtime cannot use.
|
|
###############################################################################
|
|
# PHP 8.4, not the 8.3 that composer.json's `^8.3` suggests: the lock file
|
|
# resolved Symfony 8, which requires >=8.4.1. Building on 8.3 fails at
|
|
# `composer install`, which is a much better place to find out than a deploy.
|
|
FROM dunglas/frankenphp:1-php8.4 AS base
|
|
|
|
WORKDIR /app
|
|
|
|
# gd with WebP is not optional: it is what App\Services\Media\ImageProcessor
|
|
# derives every responsive version with. exif is what stops a photo taken
|
|
# sideways staying sideways. pcntl lets the queue worker shut down cleanly
|
|
# instead of being killed mid-job.
|
|
RUN install-php-extensions \
|
|
pdo_pgsql \
|
|
gd \
|
|
exif \
|
|
intl \
|
|
zip \
|
|
pcntl \
|
|
opcache \
|
|
&& apt-get update \
|
|
&& apt-get install -y --no-install-recommends postgresql-client \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# In base rather than only in runtime, so the test stage runs under the same
|
|
# PHP settings production does — a memory limit that is only set in production
|
|
# is a memory limit nothing has tried.
|
|
COPY docker/php.ini /usr/local/etc/php/conf.d/app.ini
|
|
|
|
###############################################################################
|
|
# Dependencies
|
|
###############################################################################
|
|
FROM base AS vendor
|
|
|
|
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
|
|
|
COPY composer.json composer.lock ./
|
|
|
|
# `--no-scripts` because the post-install hooks boot the application, and the
|
|
# application cannot boot before its code is here. They are run explicitly in
|
|
# the runtime stage instead, where everything exists.
|
|
RUN composer install \
|
|
--no-dev \
|
|
--no-scripts \
|
|
--no-autoloader \
|
|
--prefer-dist \
|
|
--no-interaction
|
|
|
|
COPY . .
|
|
|
|
RUN composer dump-autoload --no-dev --optimize --classmap-authoritative
|
|
|
|
###############################################################################
|
|
# Test
|
|
#
|
|
# The production image is built with --no-dev, which leaves out the test runner
|
|
# itself. Verifying this application against Postgres therefore needs its own
|
|
# stage — see docker-compose.test.yml, and the JSON-column queries it exists to
|
|
# exercise.
|
|
###############################################################################
|
|
FROM base AS test
|
|
|
|
# Only the dev dependencies need this one, so production stays without it.
|
|
RUN install-php-extensions bcmath
|
|
|
|
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
|
|
|
COPY composer.json composer.lock ./
|
|
|
|
RUN composer install --no-scripts --no-autoloader --prefer-dist --no-interaction
|
|
|
|
COPY . .
|
|
|
|
# An empty .env: the file is excluded from the build context on purpose, and
|
|
# without it every single test emits a "failed to open stream" warning that
|
|
# buries the real output.
|
|
RUN touch .env \
|
|
&& composer dump-autoload --optimize \
|
|
&& php artisan package:discover --ansi
|
|
|
|
###############################################################################
|
|
# Runtime
|
|
###############################################################################
|
|
FROM base AS runtime
|
|
|
|
LABEL org.opencontainers.image.title="Pireon Admin" \
|
|
org.opencontainers.image.description="Admin panel and REST API for the collective"
|
|
|
|
COPY docker/Caddyfile /etc/caddy/Caddyfile
|
|
|
|
COPY --from=vendor /app/vendor ./vendor
|
|
COPY . .
|
|
|
|
COPY docker/entrypoint.sh /usr/local/bin/entrypoint
|
|
RUN chmod +x /usr/local/bin/entrypoint
|
|
|
|
# Filament serves its own CSS and JS from public/; publishing them at build
|
|
# time means the running container never writes to public/.
|
|
#
|
|
# There is deliberately no Node stage: the only `@vite` directive left is in
|
|
# Laravel's default welcome page, which this application redirects away from.
|
|
RUN php artisan package:discover --ansi \
|
|
&& php artisan filament:assets
|
|
|
|
RUN chown -R www-data:www-data storage bootstrap/cache
|
|
|
|
ENV SERVER_NAME=:80
|
|
|
|
EXPOSE 80
|
|
|
|
ENTRYPOINT ["entrypoint"]
|
|
|
|
CMD ["frankenphp", "run", "--config", "/etc/caddy/Caddyfile"]
|