# syntax=docker/dockerfile:1
# docker/php-fpm/Dockerfile — imagem do runtime PHP (ADR-031).
#
# - Base oficial `php:8.4-fpm-trixie` (Debian 13), pinada por digest.
# - Instala APENAS as extensões que a base não traz + BLAKE3 (ADR-029) + PCOV (cobertura de teste).
# - Composer vem de um estágio próprio e o binário é copiado (deploy/`up_prod.sh`).
# - Config (`user_ini.filename=`, pool, PHPRC/PHP_INI_SCAN_DIR) é MONTADA — nunca embutida (ADR-005).
# - Non-root é garantido pelo Compose (`user: "${UID}:${GID}"`).

# 8.4.27 corrige CVE-2026-109618/109619 (php2shell). O digest é o **index**
# multi-arch publicado em 2026-10-21; não volte para 8.4.26.
ARG PHP=php:8.4.27-fpm-trixie@sha256:e2d8e787dc775bdbd9d7e0c5e8f2f9ddb41ce5977c8bbaf99a2ba2e7d90fd8ae
ARG COMPOSER=composer:2@sha256:af98f42dfff7c68ba8d53c2164fd9fde1087b7d449514baa38c418b1f6bc4bac
ARG BLAKE3_REF=3d86cdaf9bcc52ebfd4c52120e987fc6a7fb2984
# SHA-256 do tarball do BLAKE3 (commit pinado acima). Sem isso, um download corrompido ou
# trocado entra na imagem sem ninguém notar (ADR-001/ADR-031: build reprodutível).
ARG BLAKE3_SHA256=6e8e428399c1fc7dc9a1cb4cb0f63d5a2ca1054bdce795ab62c0997f43e3c84a
# Versoes das extensoes PECL **pinadas** (ADR-001): sem versao, o build pode pegar uma
# versao nova e mudar o artefato sem ninguem pedir. Estas sao as que rodam com PHP 8.4.
ARG PECL_APCU=5.1.28
ARG PECL_REDIS=6.3.0
ARG PECL_IMAGICK=3.8.1
ARG PECL_PCOV=1.0.12
# SHA-256 de cada tarball PECL: o `pecl install` sozinho não garante o byte a byte.
ARG PECL_SHA_APCU=ca9c1820810a168786f8048a4c3f8c9e3fd941407ad1553259fb2e30b5f057bf
ARG PECL_SHA_REDIS=0d5141f634bd1db6c1ddcda053d25ecf2c4fc1c395430d534fd3f8d51dd7f0b5
ARG PECL_SHA_IMAGICK=3a3587c0a524c17d0dad9673a160b90cd776e836838474e173b549ed864352ee
ARG PECL_SHA_PCOV=23255c8c9335a9636ccb743f5302436a97a582a0bbde9869485be911bbc15da8

# ------------------------------------------------------------------ Composer (só o binário)
FROM ${COMPOSER} AS composer

# ------------------------------------------------------------------ Runtime PHP
FROM ${PHP} AS runtime

ARG BLAKE3_REF
ARG BLAKE3_SHA256
ARG PECL_APCU
ARG PECL_REDIS
ARG PECL_IMAGICK
ARG PECL_PCOV
ARG PECL_SHA_APCU
ARG PECL_SHA_REDIS
ARG PECL_SHA_IMAGICK
ARG PECL_SHA_PCOV

RUN set -eux; \
    apt-get update; \
    apt-get install -y --no-install-recommends \
        curl ca-certificates libicu-dev libpq-dev libzip-dev libonig-dev libmagickwand-dev \
        libvips-tools libheif-plugin-aomenc libheif-plugin-aomdec qpdf; \
    docker-php-ext-install -j"$(nproc)" intl pdo_pgsql pgsql zip bcmath exif; \
    # PECL **pinado** (ADR-001/ADR-031): versao E checksum fixos, uma extensao por vez.
    # - Uma extensao por comando: com varios pacotes numa unica chamada, o PECL instalou
    #   apenas o primeiro e o ultimo (redis e imagick foram pulados — medido no build) e o
    #   `docker-php-ext-enable` depois falhou com "redis does not exist".
    # - O CDN do pecl.php.net e intermitente: 504 foi medido em 2026-10-21 no caminho
    #   `.tgz` de uma versao que existe (redis-6.3.0) e tambem no caminho sem extensao.
    #   Por isso: duas URLs, quatro tentativas, e `sha256sum -c` garante o byte a byte.
    for spec in "apcu ${PECL_APCU} ${PECL_SHA_APCU}" "redis ${PECL_REDIS} ${PECL_SHA_REDIS}" "imagick ${PECL_IMAGICK} ${PECL_SHA_IMAGICK}" "pcov ${PECL_PCOV} ${PECL_SHA_PCOV}"; do \
        set -- $spec; name="$1"; version="$2"; sha="$3"; \
        ok=0; \
        for attempt in 1 2 3 4; do \
            for url in "https://pecl.php.net/get/${name}-${version}.tgz" "https://pecl.php.net/get/${name}-${version}"; do \
                if curl -fsSL --max-time 120 "$url" -o /tmp/pecl-pkg.tgz; then ok=1; break; fi; \
            done; \
            [ "$ok" = "1" ] && break; \
            echo "download de ${name}-${version} falhou (tentativa ${attempt}) — CDN do PECL intermitente" >&2; \
            sleep 5; \
        done; \
        [ "$ok" = "1" ] || { echo "download de ${name}-${version} falhou em 4 tentativas" >&2; exit 1; }; \
        echo "${sha}  /tmp/pecl-pkg.tgz" | sha256sum -c -; \
        pecl install /tmp/pecl-pkg.tgz; \
        rm -f /tmp/pecl-pkg.tgz; \
    done; \
    docker-php-ext-enable apcu redis imagick pcov; \
    # libvips (ADR-026 §6): CLI `vips` para digestao de imagem (AVIF/WebP). Streaming/threaded —
    # muito mais rapido e com pico de memoria menor que o ImageMagick em imagem grande.
    # `libheif-plugin-aomenc` e o encoder AVIF (o Debian 13 separa os plugins do libheif).
    vips --version; \
    # qpdf (Apache-2.0): linearizacao de PDF do servico Media (licenca permissiva — ADR-002).
    qpdf --version; \
    # BLAKE3 (ADR-029): extensao nativa ExinOne/php-blake3-ext (Apache-2.0), commit pinado.
    # Usa o C oficial BLAKE3 1.8.2 (vendorizado no repo). Expoe blake3_hash().
    apt-get install -y --no-install-recommends $PHPIZE_DEPS; \
    curl -fsSL "https://github.com/ExinOne/php-blake3-ext/archive/${BLAKE3_REF}.tar.gz" -o /tmp/blake3.tgz; \
    echo "${BLAKE3_SHA256}  /tmp/blake3.tgz" | sha256sum -c -; \
    mkdir -p /tmp/blake3; \
    tar -xzf /tmp/blake3.tgz -C /tmp/blake3 --strip-components=1; \
    ( cd /tmp/blake3 && phpize && ./configure --enable-blake3 && make -j"$(nproc)" && make install ); \
    docker-php-ext-enable blake3; \
    rm -rf /tmp/blake3 /tmp/blake3.tgz; \
    # --- Imagem menor (ADR-031): o toolchain de build nao vai para o runtime ---------
    # A limpeza fica **no mesmo RUN** de propósito: em Docker, apagar um arquivo em uma
    # layer posterior não reduz a imagem (os bytes continuam na layer anterior) — só o
    # mesmo RUN garante que eles nunca entrem. Medido: 878 MB → ~800 MB.
    # **Sem `--auto-remove`**: as bibliotecas de runtime (libicu, libpq, libzip, libonig,
    # libmagickwand) vieram como dependencia dos `-dev` e um autoremove as levaria junto
    # — quebrando as extensoes ja compiladas.
    docker-php-source delete; \
    rm -rf /tmp/pear; \
    apt-get purge -y $PHPIZE_DEPS libicu-dev libpq-dev libzip-dev libonig-dev libmagickwand-dev; \
    rm -rf /var/lib/apt/lists/*; \
    # Prova de que a limpeza nao quebrou nada: as extensoes carregam E funcionam.
    php -r 'foreach (["apcu", "redis", "imagick", "pcov", "blake3"] as $e) { if (! extension_loaded($e)) { fwrite(STDERR, "extensao ausente: $e\n"); exit(1); } } if (! function_exists("blake3_hash") || blake3_hash("x") === "") { fwrite(STDERR, "blake3_hash inoperante\n"); exit(1); } $i = new Imagick(); if (! class_exists("Redis")) { fwrite(STDERR, "Redis inoperante\n"); exit(1); }'

# Composer para `composer install` no deploy — sem imagem extra.
COPY --from=composer /usr/bin/composer /usr/local/bin/composer

# Sanidade do "ignorar cPanel" (ADR-005) — apenas alerta, não falha.
COPY docker/php-fpm/entrypoint.sh /usr/local/bin/php-entrypoint.sh
RUN chmod +x /usr/local/bin/php-entrypoint.sh

# Garante que o PHP ignore o php.ini/.user.ini do docroot (não depende do cwd).
ENV PHPRC=/usr/local/etc/php \
    PHP_INI_SCAN_DIR=/usr/local/etc/php/conf.d

WORKDIR /var/www/html

ENTRYPOINT ["/usr/local/bin/php-entrypoint.sh"]
CMD ["php-fpm", "--nodaemonize"]
