customer-riverside/Dockerfile
Philip Peterson dcb58bbb3a
All checks were successful
deploy / image (push) Successful in 5m17s
Serve Preact from the site: the components rendered nothing
Every component imported Preact, its hooks and htm/preact from esm.sh
separately. htm/preact imports Preact unversioned, which esm.sh now
resolves to Preact 11, while the components asked for preact@10: two
Preacts on one page, so render() drew nothing, silently. Booking, FAQ,
testimonials, carousel, toggle and appointment type were all blank.

Use htm's single-file standalone build instead (Preact 10, its hooks and
html in one module, no further imports), downloaded at image build
pinned by version and checksum, like FullCalendar, and imported from
../vendor/preact-standalone.js. Checked on the live page: the booking
component renders again with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 06:08:05 -09:00

134 lines
5.9 KiB
Docker

# PHP for both PHP stages, pinned: bump on purpose (8.5.12 fixes the
# PHP2Shell RCEs, CVE-2026-109618 and CVE-2026-109619).
ARG PHP_VERSION=8.5.12
# ── Stage 1: CSS build ────────────────────────────────────────────────────────
FROM node:22-slim AS node-build
WORKDIR /build
COPY package.json tailwind.config.js ./
RUN npm install --include=dev
# Copy only what Tailwind needs to scan + the input CSS
COPY web/modules/custom/riverside_pt/css/tailwind.css \
web/modules/custom/riverside_pt/css/tailwind.css
COPY web/modules/custom/riverside_pt/templates/ \
web/modules/custom/riverside_pt/templates/
COPY web/modules/custom/riverside_pt/src/ \
web/modules/custom/riverside_pt/src/
COPY web/modules/custom/riverside_pt/js/components/ \
web/modules/custom/riverside_pt/js/components/
RUN npm run build
# ── Stage 2: PHP extensions + Composer deps ───────────────────────────────────
FROM php:${PHP_VERSION}-fpm AS php-build
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq-dev \
libpng-dev \
libjpeg-dev \
libfreetype-dev \
libzip-dev \
git \
unzip \
curl \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j"$(nproc)" \
pdo_pgsql \
pgsql \
gd \
zip \
exif \
bcmath \
&& rm -rf /var/lib/apt/lists/*
RUN curl -fsSL https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
WORKDIR /var/www/html
COPY composer.json ./
RUN composer config repositories.drupal composer https://packages.drupal.org/8 \
&& composer require \
composer/installers:^2.3 \
drupal/core-recommended:^11 \
drupal/core-composer-scaffold:^11 \
"drush/drush:^13 || ^14" \
drupal/webform \
drupal/symfony_mailer \
drupal/claro_compact \
--no-update \
&& composer install --no-dev --optimize-autoloader --no-interaction \
&& rm -rf /root/.composer/cache
# ── Stage 3: Runtime image ────────────────────────────────────────────────────
FROM php:${PHP_VERSION}-fpm
# ── System packages ───────────────────────────────────────────────────────────
RUN apt-get update && apt-get install -y --no-install-recommends \
nginx \
supervisor \
postgresql-client \
libpq-dev \
libpng-dev \
libjpeg-dev \
libfreetype-dev \
libzip-dev \
locales \
curl \
gettext-base \
procps \
&& rm -rf /var/lib/apt/lists/*
# ── PHP extensions from build stage ──────────────────────────────────────────
COPY --from=php-build /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
COPY --from=php-build /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/
# Session upload progress off: it's where PHP2Shell (CVE-2026-109618/9) and
# later bugs live, and Drupal doesn't use it.
RUN echo 'session.upload_progress.enabled = 0' > /usr/local/etc/php/conf.d/zz-security.ini
# ── All system config — done before the big vendor COPY so VFS snapshots are small ──
RUN rm -f /etc/nginx/sites-enabled/default
COPY docker/nginx/default.conf /etc/nginx/conf.d/default.conf.template
COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY docker/php/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh \
&& sed -i 's|;error_log = log/php-fpm.log|error_log = /var/log/php-fpm.log|' /usr/local/etc/php-fpm.conf \
&& { \
echo 'clear_env = no'; \
echo 'catch_workers_output = yes'; \
echo 'php_admin_flag[log_errors] = on'; \
echo 'php_admin_value[error_log] = /var/log/php-fpm.www.log'; \
} >> /usr/local/etc/php-fpm.d/zz-env.conf
ENV PATH="/var/www/html/vendor/bin:${PATH}"
WORKDIR /var/www/html
# ── Large data layers (VFS snapshots are expensive past this point) ───────────
# Scaffolded vendor/ + web/ from composer stage
COPY --from=php-build /var/www/html/ ./
# Site-specific overlays on top of the scaffold
COPY web/sites/default/settings.php web/sites/default/settings.php
COPY web/sites/default/files/ web/sites/default/files/
COPY web/modules/custom/ web/modules/custom/
COPY --from=node-build /build/web/modules/custom/riverside_pt/css/app.css \
web/modules/custom/riverside_pt/css/app.css
COPY config/sync/ config/sync/
# Download FullCalendar and Preact, and lock settings.php in one layer.
# Preact (with its hooks and htm's html``) is htm's single-file standalone
# build, served from the site: the components used to import Preact, its
# hooks and htm/preact from esm.sh separately, and when htm/preact started
# resolving to Preact 11 while the rest stayed on 10, every component
# rendered nothing. Pinned by version and checksum.
ARG FULLCALENDAR_VERSION=6.1.15
ARG HTM_VERSION=3.1.1
ARG HTM_PREACT_STANDALONE_SHA256=72284e8e9079c87817145df1110f74e8a2aa040b2fc384922e18dfcb46fc1fd7
RUN curl -fsSL "https://cdn.jsdelivr.net/npm/fullcalendar@${FULLCALENDAR_VERSION}/index.global.min.js" \
-o web/modules/custom/riverside_pt/js/fullcalendar.min.js \
&& mkdir -p web/modules/custom/riverside_pt/js/vendor \
&& curl -fsSL "https://cdn.jsdelivr.net/npm/htm@${HTM_VERSION}/preact/standalone.module.js" \
-o web/modules/custom/riverside_pt/js/vendor/preact-standalone.js \
&& echo "${HTM_PREACT_STANDALONE_SHA256} web/modules/custom/riverside_pt/js/vendor/preact-standalone.js" | sha256sum -c - \
&& chmod 444 web/sites/default/settings.php
EXPOSE 80
ENTRYPOINT ["/entrypoint.sh"]