Files
Vasyka 9b97e101ff security: patch PHP2Shell RCE CVE-2026-109618 + CVE-2026-109619
Pin base image from floating dunglas/frankenphp:1-php8.4 to
dunglas/frankenphp:1.13.4-php8.4.27 which ships PHP 8.4.27.

CVE-2026-109618: OOM memory corruption → unauthenticated RCE (CVSS 9.2)
CVE-2026-109619: use-after-free between requests → unauthenticated RCE (CVSS 9.2)
Both affect PHP-FPM, mod_php, FrankenPHP, php-cgi. Exploited in the wild.
Fixed upstream in PHP 8.2.35, 8.3.36, 8.4.27, 8.5.12.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-10-27 09:17:22 +00:00

114 lines
3.5 KiB
Docker

# syntax=docker/dockerfile:1.7
# AutoCRM — Laravel 12 + Filament + Octane FrankenPHP
# Multi-stage: composer install + npm build + runtime
# ─── Stage 1: Composer dependencies ───────────────────────────
FROM composer:2 AS composer
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install \
--no-dev \
--no-interaction \
--no-progress \
--no-scripts \
--prefer-dist \
--optimize-autoloader \
--ignore-platform-reqs
# ─── Stage 2: Node assets (Vite) ──────────────────────────────
FROM node:22-alpine AS node
WORKDIR /app
COPY package.json package-lock.json* ./
RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
COPY resources ./resources
COPY vite.config.js ./
COPY public ./public
RUN npm run build
# ─── Stage 3: Runtime (FrankenPHP + PHP 8.4) ──────────────────
# Pinned to 1.13.4-php8.4.27 — fixes PHP2Shell RCE (CVE-2026-109618, CVE-2026-109619)
FROM dunglas/frankenphp:1.13.4-php8.4.27 AS runtime
WORKDIR /app
# Install PHP extensions Laravel needs
RUN install-php-extensions \
pdo_mysql \
pcntl \
bcmath \
intl \
gd \
zip \
redis \
opcache \
pcntl \
sockets \
exif \
curl \
mbstring \
gmp
# System tools + Chromium + Node.js (for spatie/browsershot PDF rendering)
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
unzip \
curl \
ca-certificates \
gnupg \
chromium \
fonts-liberation \
fonts-noto \
fonts-noto-cjk \
&& curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& rm -rf /var/lib/apt/lists/*
# Puppeteer + Browsershot deps live in a shared node_modules under /app
# so Browsershot can spawn `node`+puppeteer bundled with Chromium bindings.
RUN mkdir -p /opt/browsershot && cd /opt/browsershot \
&& npm install --omit=dev puppeteer-core@23 \
&& chown -R www-data:www-data /opt/browsershot
ENV BROWSERSHOT_NODE_BINARY=/usr/bin/node \
BROWSERSHOT_NPM_BINARY=/usr/bin/npm \
BROWSERSHOT_NODE_MODULE_PATH=/opt/browsershot/node_modules \
BROWSERSHOT_CHROME_PATH=/usr/bin/chromium
# Copy application code
COPY --link . /app
# Composer vendor from stage 1
COPY --from=composer --link /app/vendor /app/vendor
# Built assets from stage 2
COPY --from=node --link /app/public/build /app/public/build
# Permissions
RUN chown -R www-data:www-data storage bootstrap/cache \
&& chmod -R 0775 storage bootstrap/cache
# OPcache production config
RUN { \
echo "opcache.enable=1"; \
echo "opcache.enable_cli=1"; \
echo "opcache.jit_buffer_size=128M"; \
echo "opcache.jit=tracing"; \
echo "opcache.memory_consumption=256"; \
echo "opcache.max_accelerated_files=20000"; \
echo "opcache.validate_timestamps=0"; \
} > /usr/local/etc/php/conf.d/opcache.ini
ENV OCTANE_SERVER=frankenphp \
APP_BASE_PATH=/app \
SERVER_NAME=":8000"
EXPOSE 8000
# Healthcheck
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
CMD curl -fsSL http://localhost:8000/up || exit 1
# Entrypoint script handles migrations + cache
COPY docker/entrypoint.sh /usr/local/bin/entrypoint
RUN chmod +x /usr/local/bin/entrypoint
ENTRYPOINT ["/usr/local/bin/entrypoint"]
CMD ["php", "artisan", "octane:start", "--server=frankenphp", "--host=0.0.0.0", "--port=8000", "--admin-port=2019", "--workers=auto", "--max-requests=500"]