From 85d5b1a1fde08926f62b1fd923057a6590504f3a Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 14:45:01 -0400 Subject: [PATCH 01/15] added AIO images --- aio/Dockerfile | 49 ++++++++++++++++++++++++++++++++ aio/Dockerfile-headless | 63 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 aio/Dockerfile create mode 100644 aio/Dockerfile-headless diff --git a/aio/Dockerfile b/aio/Dockerfile new file mode 100644 index 0000000..edbac37 --- /dev/null +++ b/aio/Dockerfile @@ -0,0 +1,49 @@ +# Normal Operations for setup of Apache and ENV Vars +# Allow building different PHP versions from build args (CI uses PHP_VERSION) +ARG PHP_VERSION=8.3 +ARG PHP_TAG=${PHP_VERSION}-apache +FROM php:${PHP_TAG} AS base + +# Configure OPCache +ENV PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 +ENV PHP_OPCACHE_MAX_ACCELERATED_FILES=10000 +ENV PHP_OPCACHE_MEMORY_CONSUMPTION=192 +ENV PHP_OPCACHE_MAX_WASTED_PERCENTAGE=10 + +COPY common/opcache.ini /usr/local/etc/php/conf.d/opcache.ini + +RUN apt-get update -y; \ + apt-get install -y openssl zip unzip git wget iputils-ping libpng-dev libzip-dev libmagickwand-dev --no-install-recommends; \ + docker-php-ext-install gd zip pdo mysqli pdo_mysql opcache; \ + pecl install redis; \ + pecl install imagick; \ + docker-php-ext-enable redis; \ + docker-php-ext-enable imagick; \ + apt autoremove -y; \ + curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer; \ + rm -rf /var/lib/apt/lists/*; + +FROM base + +# Configure Apache and combine many small RUN steps into a single layer to +# reduce image size and improve caching. +# This groups enabling modules, adding configs, making files executable and adjusting Apache settings. +COPY common/remoteip-env /usr/sbin +COPY common/remoteip-clear /usr/sbin +COPY common/opcache-preload /usr/sbin +COPY common/opcache-status /usr/sbin + +RUN set -eux; \ + a2enmod rewrite remoteip; \ + touch /etc/apache2/conf-available/remoteip.conf; \ + ln -s /etc/apache2/conf-available/remoteip.conf /etc/apache2/conf-enabled/remoteip.conf || true; \ + chmod +x /usr/sbin/remoteip-* /usr/sbin/opcache-* || true; \ + sed -ri -e 's!AllowOverride None!AllowOverride All!g' /etc/apache2/apache2.conf; \ + sed -ri -e 's!Listen 80!Listen 8181!g' /etc/apache2/ports.conf; \ + sed -ri -e 's!VirtualHost \*:80!VirtualHost \*:8181!g' /etc/apache2/sites-enabled/000-default.conf; \ + echo "ServerSignature off" >> /etc/apache2/apache2.conf; \ + echo "ServerTokens Prod" >> /etc/apache2/apache2.conf; \ + sed -ri -e 's!#LoadModule remoteip_module!LoadModule remoteip_module!g' /etc/apache2/apache2.conf; \ + sed -ri -e 's/LogFormat .* combined/LogFormat "%a %{c}a %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-Agent}i\\\" %I %O" combined/g' /etc/apache2/apache2.conf + +EXPOSE 8181 \ No newline at end of file diff --git a/aio/Dockerfile-headless b/aio/Dockerfile-headless new file mode 100644 index 0000000..e066c17 --- /dev/null +++ b/aio/Dockerfile-headless @@ -0,0 +1,63 @@ +# Normal Operations for setup of Apache and ENV Vars +# Allow building different PHP versions from build args (CI uses PHP_VERSION) +ARG PHP_VERSION=8.3 +ARG PHP_TAG=${PHP_VERSION}-apache +FROM php:${PHP_TAG} AS base + +# Configure OPCache +ENV PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 +ENV PHP_OPCACHE_MAX_ACCELERATED_FILES=10000 +ENV PHP_OPCACHE_MEMORY_CONSUMPTION=192 +ENV PHP_OPCACHE_MAX_WASTED_PERCENTAGE=10 + +COPY common/opcache.ini /usr/local/etc/php/conf.d/opcache.ini + +RUN apt-get update -y; \ + apt-get install -y openssl zip unzip git wget iputils-ping libpng-dev libzip-dev libmagickwand-dev --no-install-recommends; \ + docker-php-ext-install gd zip pdo mysqli pdo_mysql opcache; \ + pecl install redis; \ + pecl install imagick; \ + docker-php-ext-enable redis; \ + docker-php-ext-enable imagick; \ + apt autoremove -y; \ + curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer; \ + rm -rf /var/lib/apt/lists/*; + +FROM base AS browser + +# As needed for Chrome to Run +# https://github.com/beganovich/snappdf#downloading-local-chromium +# https://github.com/beganovich/snappdf?tab=readme-ov-file#headless-chrome-doesnt-launch-on-unix +RUN apt-get update -y; \ + apt-get install -y ca-certificates fonts-liberation libnss3 libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 lsb-release xdg-utils --no-install-recommends; \ + rm -rf /var/lib/apt/lists/*; + +FROM browser + +# Configure Apache and combine many small RUN steps into a single layer to +# reduce image size and improve caching. +# This groups enabling modules, adding configs, making files executable and adjusting Apache settings. +COPY common/remoteip-env /usr/sbin +COPY common/remoteip-clear /usr/sbin +COPY common/opcache-preload /usr/sbin +COPY common/opcache-status /usr/sbin + +RUN set -eux; \ + a2enmod rewrite remoteip; \ + touch /etc/apache2/conf-available/remoteip.conf; \ + ln -s /etc/apache2/conf-available/remoteip.conf /etc/apache2/conf-enabled/remoteip.conf || true; \ + chmod +x /usr/sbin/remoteip-* /usr/sbin/opcache-* || true; \ + sed -ri -e 's!AllowOverride None!AllowOverride All!g' /etc/apache2/apache2.conf; \ + sed -ri -e 's!Listen 80!Listen 8181!g' /etc/apache2/ports.conf; \ + sed -ri -e 's!VirtualHost \*:80!VirtualHost \*:8181!g' /etc/apache2/sites-enabled/000-default.conf; \ + echo "ServerSignature off" >> /etc/apache2/apache2.conf; \ + echo "ServerTokens Prod" >> /etc/apache2/apache2.conf; \ + sed -ri -e 's!#LoadModule remoteip_module!LoadModule remoteip_module!g' /etc/apache2/apache2.conf; \ + sed -ri -e 's/LogFormat .* combined/LogFormat "%a %{c}a %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-Agent}i\\\" %I %O" combined/g' /etc/apache2/apache2.conf + +EXPOSE 8181 + + + + + From be1848f275abe25edd3610beb5b996952d14a959 Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 16:08:36 -0400 Subject: [PATCH 02/15] added apache status endpoint and removed git replaced wget with curl and removed ping util --- aio/Dockerfile | 18 +++++++++++------- aio/Dockerfile-headless | 11 ++++++++--- common/apache-status | 12 ++++++++++++ common/healthz.html | 1 + common/status.conf | 18 ++++++++++++++++++ 5 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 common/apache-status create mode 100644 common/healthz.html create mode 100644 common/status.conf diff --git a/aio/Dockerfile b/aio/Dockerfile index edbac37..6e0468f 100644 --- a/aio/Dockerfile +++ b/aio/Dockerfile @@ -13,7 +13,7 @@ ENV PHP_OPCACHE_MAX_WASTED_PERCENTAGE=10 COPY common/opcache.ini /usr/local/etc/php/conf.d/opcache.ini RUN apt-get update -y; \ - apt-get install -y openssl zip unzip git wget iputils-ping libpng-dev libzip-dev libmagickwand-dev --no-install-recommends; \ + apt-get install -y openssl zip unzip curl libpng-dev libzip-dev libmagickwand-dev --no-install-recommends; \ docker-php-ext-install gd zip pdo mysqli pdo_mysql opcache; \ pecl install redis; \ pecl install imagick; \ @@ -25,25 +25,29 @@ RUN apt-get update -y; \ FROM base -# Configure Apache and combine many small RUN steps into a single layer to -# reduce image size and improve caching. -# This groups enabling modules, adding configs, making files executable and adjusting Apache settings. +# Configure Apache: combine multiple small RUNs into one layer to reduce image size +# Copy scripts and config files first so they can be used in the same layer COPY common/remoteip-env /usr/sbin COPY common/remoteip-clear /usr/sbin COPY common/opcache-preload /usr/sbin COPY common/opcache-status /usr/sbin +COPY common/apache-status /usr/sbin +COPY common/status.conf /etc/apache2/sites-enabled/000-status.conf +COPY common/healthz.html /var/www/html/healthz.html RUN set -eux; \ - a2enmod rewrite remoteip; \ + a2enmod rewrite remoteip status; \ touch /etc/apache2/conf-available/remoteip.conf; \ ln -s /etc/apache2/conf-available/remoteip.conf /etc/apache2/conf-enabled/remoteip.conf || true; \ - chmod +x /usr/sbin/remoteip-* /usr/sbin/opcache-* || true; \ + chmod +x /usr/sbin/remoteip-* /usr/sbin/opcache-* /usr/sbin/apache-status || true; \ sed -ri -e 's!AllowOverride None!AllowOverride All!g' /etc/apache2/apache2.conf; \ sed -ri -e 's!Listen 80!Listen 8181!g' /etc/apache2/ports.conf; \ sed -ri -e 's!VirtualHost \*:80!VirtualHost \*:8181!g' /etc/apache2/sites-enabled/000-default.conf; \ echo "ServerSignature off" >> /etc/apache2/apache2.conf; \ echo "ServerTokens Prod" >> /etc/apache2/apache2.conf; \ + printf '\n\n Listen 8282\n\n' >> /etc/apache2/ports.conf; \ sed -ri -e 's!#LoadModule remoteip_module!LoadModule remoteip_module!g' /etc/apache2/apache2.conf; \ sed -ri -e 's/LogFormat .* combined/LogFormat "%a %{c}a %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-Agent}i\\\" %I %O" combined/g' /etc/apache2/apache2.conf -EXPOSE 8181 \ No newline at end of file +EXPOSE 8181 +EXPOSE 8282 \ No newline at end of file diff --git a/aio/Dockerfile-headless b/aio/Dockerfile-headless index e066c17..68c4878 100644 --- a/aio/Dockerfile-headless +++ b/aio/Dockerfile-headless @@ -13,7 +13,7 @@ ENV PHP_OPCACHE_MAX_WASTED_PERCENTAGE=10 COPY common/opcache.ini /usr/local/etc/php/conf.d/opcache.ini RUN apt-get update -y; \ - apt-get install -y openssl zip unzip git wget iputils-ping libpng-dev libzip-dev libmagickwand-dev --no-install-recommends; \ + apt-get install -y openssl zip unzip curl libpng-dev libzip-dev libmagickwand-dev --no-install-recommends; \ docker-php-ext-install gd zip pdo mysqli pdo_mysql opcache; \ pecl install redis; \ pecl install imagick; \ @@ -41,21 +41,26 @@ COPY common/remoteip-env /usr/sbin COPY common/remoteip-clear /usr/sbin COPY common/opcache-preload /usr/sbin COPY common/opcache-status /usr/sbin +COPY common/apache-status /usr/sbin +COPY common/status.conf /etc/apache2/sites-enabled/000-status.conf +COPY common/healthz.html /var/www/html/healthz.html RUN set -eux; \ - a2enmod rewrite remoteip; \ + a2enmod rewrite remoteip status; \ touch /etc/apache2/conf-available/remoteip.conf; \ ln -s /etc/apache2/conf-available/remoteip.conf /etc/apache2/conf-enabled/remoteip.conf || true; \ - chmod +x /usr/sbin/remoteip-* /usr/sbin/opcache-* || true; \ + chmod +x /usr/sbin/remoteip-* /usr/sbin/opcache-* /usr/sbin/apache-status || true; \ sed -ri -e 's!AllowOverride None!AllowOverride All!g' /etc/apache2/apache2.conf; \ sed -ri -e 's!Listen 80!Listen 8181!g' /etc/apache2/ports.conf; \ sed -ri -e 's!VirtualHost \*:80!VirtualHost \*:8181!g' /etc/apache2/sites-enabled/000-default.conf; \ echo "ServerSignature off" >> /etc/apache2/apache2.conf; \ echo "ServerTokens Prod" >> /etc/apache2/apache2.conf; \ + printf '\n\n Listen 8282\n\n' >> /etc/apache2/ports.conf; \ sed -ri -e 's!#LoadModule remoteip_module!LoadModule remoteip_module!g' /etc/apache2/apache2.conf; \ sed -ri -e 's/LogFormat .* combined/LogFormat "%a %{c}a %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-Agent}i\\\" %I %O" combined/g' /etc/apache2/apache2.conf EXPOSE 8181 +EXPOSE 8282 diff --git a/common/apache-status b/common/apache-status new file mode 100644 index 0000000..35bce69 --- /dev/null +++ b/common/apache-status @@ -0,0 +1,12 @@ +#!/bin/bash + +URL="127.0.0.1:8282/server-status?auto" + +if command -v curl >/dev/null 2>&1; then + curl -fsS "$URL" +elif command -v wget >/dev/null 2>&1; then + wget -q -O - "$URL" +else + echo "Error: neither curl nor wget is installed" >&2 + exit 1 +fi diff --git a/common/healthz.html b/common/healthz.html new file mode 100644 index 0000000..a0aba93 --- /dev/null +++ b/common/healthz.html @@ -0,0 +1 @@ +OK \ No newline at end of file diff --git a/common/status.conf b/common/status.conf new file mode 100644 index 0000000..57f50da --- /dev/null +++ b/common/status.conf @@ -0,0 +1,18 @@ + + + SetHandler server-status + Require all granted + # Order deny,allow + # Deny from all + # Allow from 127.0.0.1 # Allow access only from localhost + + + DocumentRoot /var/www/html + + Alias /healthz /var/www/html/healthz.html + + ForceType text/plain + + + CustomLog ${APACHE_LOG_DIR}/access.log combined + \ No newline at end of file From 1697080bd18491975216a645bced96032d454049 Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 16:08:43 -0400 Subject: [PATCH 03/15] Create build-test.yml --- .github/workflows/build-test.yml | 68 ++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 .github/workflows/build-test.yml diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml new file mode 100644 index 0000000..b90bd98 --- /dev/null +++ b/.github/workflows/build-test.yml @@ -0,0 +1,68 @@ +name: Build Docker Images + +permissions: + contents: read + +on: + workflow_dispatch: {} + pull_request: + types: [opened, synchronize] + paths-ignore: + - "README.md" + - "docker-compose.yml" + - "examples/**" + - ".run/**" + - ".circleci/**" + +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-24.04 # ubuntu-latest + timeout-minutes: 10 + + strategy: + matrix: + php_version: ['8.5', '8.4', '8.3', '8.1', '8.0'] + variant: ['apache', 'apache-chrome'] + + steps: + - name: Checkout Code + uses: actions/checkout@v6 + + - name: Github Short SHA + run: | + echo "GITHUB_SHA_SHORT=$(echo $GITHUB_SHA | cut -c 1-7)" >> $GITHUB_ENV + + - name: Set variables + run: | + if [ "${{ matrix.variant }}" == "apache" ]; then + echo "DOCKER_TAG=pr_${{ github.event.number }}_${{ matrix.php_version }}" >> $GITHUB_ENV + echo "DOCKER_FILE=Dockerfile" >> $GITHUB_ENV + elif [ "${{ matrix.variant }}" == "apache-chrome" ]; then + echo "DOCKER_TAG=pr_${{ github.event.number }}_${{ matrix.php_version }}-headless" >> $GITHUB_ENV + echo "DOCKER_FILE=Dockerfile-headless" >> $GITHUB_ENV + else + echo "Invalid variant: ${{ matrix.variant }}" + exit 1 + fi + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Build and push + uses: docker/build-push-action@v7 + with: + context: . + file: ./aio/${{ env.DOCKER_FILE }} + tags: + ghcr.io/${{ github.repository }}:${{ env.DOCKER_TAG }}, + ghcr.io/${{ github.repository }}:${{ env.GITHUB_SHA_SHORT }} + build-args: | + PHP_VERSION="${{ matrix.php_version }}" + push: false + platforms: linux/amd64,linux/arm64 + cache-from: type=gha + cache-to: type=gha,mode=max From 854e168f5ced382ab5b07e37f3d14f91e9c7401d Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 16:10:13 -0400 Subject: [PATCH 04/15] Update build-test.yml --- .github/workflows/build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index b90bd98..07e46a4 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -1,4 +1,4 @@ -name: Build Docker Images +name: Test Building Docker Images permissions: contents: read From ff5f69752387aeb2226c40e4683135d9ca0b4e83 Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 16:14:15 -0400 Subject: [PATCH 05/15] Update build-test.yml --- .github/workflows/build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 07e46a4..7b769b4 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -61,7 +61,7 @@ jobs: ghcr.io/${{ github.repository }}:${{ env.DOCKER_TAG }}, ghcr.io/${{ github.repository }}:${{ env.GITHUB_SHA_SHORT }} build-args: | - PHP_VERSION="${{ matrix.php_version }}" + PHP_VERSION=${{ matrix.php_version }} push: false platforms: linux/amd64,linux/arm64 cache-from: type=gha From e9a9b8ae8b38ce369526d028f8534a30a752816a Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 22:24:42 -0400 Subject: [PATCH 06/15] make docker-php-ext-install install in parallel --- aio/Dockerfile | 8 +++----- aio/Dockerfile-headless | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/aio/Dockerfile b/aio/Dockerfile index 6e0468f..012cf79 100644 --- a/aio/Dockerfile +++ b/aio/Dockerfile @@ -14,11 +14,9 @@ COPY common/opcache.ini /usr/local/etc/php/conf.d/opcache.ini RUN apt-get update -y; \ apt-get install -y openssl zip unzip curl libpng-dev libzip-dev libmagickwand-dev --no-install-recommends; \ - docker-php-ext-install gd zip pdo mysqli pdo_mysql opcache; \ - pecl install redis; \ - pecl install imagick; \ - docker-php-ext-enable redis; \ - docker-php-ext-enable imagick; \ + docker-php-ext-install -j"$(nproc)" gd zip pdo mysqli pdo_mysql opcache; \ + pecl install redis imagick; \ + docker-php-ext-enable -j"$(nproc)" redis imagick; \ apt autoremove -y; \ curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer; \ rm -rf /var/lib/apt/lists/*; diff --git a/aio/Dockerfile-headless b/aio/Dockerfile-headless index 68c4878..17092ba 100644 --- a/aio/Dockerfile-headless +++ b/aio/Dockerfile-headless @@ -14,11 +14,9 @@ COPY common/opcache.ini /usr/local/etc/php/conf.d/opcache.ini RUN apt-get update -y; \ apt-get install -y openssl zip unzip curl libpng-dev libzip-dev libmagickwand-dev --no-install-recommends; \ - docker-php-ext-install gd zip pdo mysqli pdo_mysql opcache; \ - pecl install redis; \ - pecl install imagick; \ - docker-php-ext-enable redis; \ - docker-php-ext-enable imagick; \ + docker-php-ext-install -j"$(nproc)" gd zip pdo mysqli pdo_mysql opcache; \ + pecl install redis imagick; \ + docker-php-ext-enable -j"$(nproc)" redis imagick; \ apt autoremove -y; \ curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer; \ rm -rf /var/lib/apt/lists/*; From 53e1a2ecdc96984dc08483dab7eaf3a1da08af33 Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 22:41:35 -0400 Subject: [PATCH 07/15] Update build-test.yml --- .github/workflows/build-test.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 7b769b4..a0b55cb 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -27,6 +27,7 @@ jobs: matrix: php_version: ['8.5', '8.4', '8.3', '8.1', '8.0'] variant: ['apache', 'apache-chrome'] + platform: ['linux/amd64','linux/arm64'] steps: - name: Checkout Code @@ -52,6 +53,13 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 + - name: Docker meta + id: meta + uses: docker/metadata-action@v6 + with: + # list of Docker images to use as base name for tags + images: | + - name: Build and push uses: docker/build-push-action@v7 with: @@ -60,9 +68,11 @@ jobs: tags: ghcr.io/${{ github.repository }}:${{ env.DOCKER_TAG }}, ghcr.io/${{ github.repository }}:${{ env.GITHUB_SHA_SHORT }} + labels: ${{ steps.meta.outputs.labels }} build-args: | PHP_VERSION=${{ matrix.php_version }} push: false - platforms: linux/amd64,linux/arm64 + provenance: mode=max + platforms: ${{ matrix.platform }} cache-from: type=gha cache-to: type=gha,mode=max From abc229f4f157b2ace595f122942e9ac0787e4881 Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 22:42:46 -0400 Subject: [PATCH 08/15] Update build-test.yml --- .github/workflows/build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index a0b55cb..97446cd 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -25,7 +25,7 @@ jobs: strategy: matrix: - php_version: ['8.5', '8.4', '8.3', '8.1', '8.0'] + php_version: ['8.5'] # , '8.4', '8.3', '8.1', '8.0'] variant: ['apache', 'apache-chrome'] platform: ['linux/amd64','linux/arm64'] From 171bbfc93dced0104c29c1c632202162cc298201 Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 22:56:32 -0400 Subject: [PATCH 09/15] split the build job to run on ARM and AMD runners --- .github/workflows/build-test.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 97446cd..8762ed2 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -20,14 +20,20 @@ concurrency: jobs: build: - runs-on: ubuntu-24.04 # ubuntu-latest + name: Build ${{ matrix.platform }} ${{ matrix.variant }} ${{ matrix.php_version }} + runs-on: ${{ matrix.runner }} timeout-minutes: 10 strategy: + fail-fast: false matrix: php_version: ['8.5'] # , '8.4', '8.3', '8.1', '8.0'] variant: ['apache', 'apache-chrome'] - platform: ['linux/amd64','linux/arm64'] + include: + - platform: linux/amd64 + runner: ubuntu-24.04 # ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm # ubuntu-latest steps: - name: Checkout Code From bc9abd598acff7625515d238ab2b924f78cfdd43 Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 23:02:41 -0400 Subject: [PATCH 10/15] Update build-test.yml --- .github/workflows/build-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 8762ed2..1a0d96a 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -21,7 +21,7 @@ concurrency: jobs: build: name: Build ${{ matrix.platform }} ${{ matrix.variant }} ${{ matrix.php_version }} - runs-on: ${{ matrix.runner }} + runs-on: ${{ matrix.target.runner }} timeout-minutes: 10 strategy: @@ -29,7 +29,7 @@ jobs: matrix: php_version: ['8.5'] # , '8.4', '8.3', '8.1', '8.0'] variant: ['apache', 'apache-chrome'] - include: + target: - platform: linux/amd64 runner: ubuntu-24.04 # ubuntu-latest - platform: linux/arm64 @@ -79,6 +79,6 @@ jobs: PHP_VERSION=${{ matrix.php_version }} push: false provenance: mode=max - platforms: ${{ matrix.platform }} + platforms: ${{ matrix.target.platform }} cache-from: type=gha cache-to: type=gha,mode=max From e74c757907db8b0773c42e9964758bce5b6c4cc4 Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 23:07:35 -0400 Subject: [PATCH 11/15] Update build-test.yml --- .github/workflows/build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 1a0d96a..57d5efe 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -20,7 +20,7 @@ concurrency: jobs: build: - name: Build ${{ matrix.platform }} ${{ matrix.variant }} ${{ matrix.php_version }} + name: Build ${{ matrix.target.platform }} ${{ matrix.variant }} ${{ matrix.php_version }} runs-on: ${{ matrix.target.runner }} timeout-minutes: 10 From b95058092781e75e6e2022afc3802b772852fb84 Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 23:10:26 -0400 Subject: [PATCH 12/15] Update build-test.yml --- .github/workflows/build-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 57d5efe..faa18a6 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -27,7 +27,7 @@ jobs: strategy: fail-fast: false matrix: - php_version: ['8.5'] # , '8.4', '8.3', '8.1', '8.0'] + php_version: ['8.5' , '8.4', '8.3', '8.1', '8.0'] variant: ['apache', 'apache-chrome'] target: - platform: linux/amd64 @@ -78,7 +78,7 @@ jobs: build-args: | PHP_VERSION=${{ matrix.php_version }} push: false - provenance: mode=max + provenance: mode=min platforms: ${{ matrix.target.platform }} cache-from: type=gha cache-to: type=gha,mode=max From 97678a54d6927457b9d0a5ae20a65e3e03d02e08 Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 23:42:33 -0400 Subject: [PATCH 13/15] Update build-test.yml --- .github/workflows/build-test.yml | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index faa18a6..922d0ec 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -1,4 +1,4 @@ -name: Test Building Docker Images +name: Test Build Images on PR permissions: contents: read @@ -27,22 +27,23 @@ jobs: strategy: fail-fast: false matrix: - php_version: ['8.5' , '8.4', '8.3', '8.1', '8.0'] + php_version: ['8.5' , '8.4', '8.3', '8.1', '8.0', '7.4'] variant: ['apache', 'apache-chrome'] target: - platform: linux/amd64 runner: ubuntu-24.04 # ubuntu-latest + artifact_suffix: linux-amd64 - platform: linux/arm64 runner: ubuntu-24.04-arm # ubuntu-latest + artifact_suffix: linux-arm64 + exclude: + - php_version: '7.4' + variant: 'apache-chrome' steps: - name: Checkout Code uses: actions/checkout@v6 - - name: Github Short SHA - run: | - echo "GITHUB_SHA_SHORT=$(echo $GITHUB_SHA | cut -c 1-7)" >> $GITHUB_ENV - - name: Set variables run: | if [ "${{ matrix.variant }}" == "apache" ]; then @@ -59,26 +60,19 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 - - name: Docker meta - id: meta - uses: docker/metadata-action@v6 - with: - # list of Docker images to use as base name for tags - images: | + - name: Login to GitHub Container Registry + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin - - name: Build and push + - name: Build and push by digest + id: build uses: docker/build-push-action@v7 with: context: . file: ./aio/${{ env.DOCKER_FILE }} - tags: - ghcr.io/${{ github.repository }}:${{ env.DOCKER_TAG }}, - ghcr.io/${{ github.repository }}:${{ env.GITHUB_SHA_SHORT }} - labels: ${{ steps.meta.outputs.labels }} build-args: | PHP_VERSION=${{ matrix.php_version }} + platforms: ${{ matrix.target.platform }} push: false provenance: mode=min - platforms: ${{ matrix.target.platform }} cache-from: type=gha cache-to: type=gha,mode=max From 969d5ccbe1b35c032078e24bff00b273c7d23e37 Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 23:47:57 -0400 Subject: [PATCH 14/15] migrate main build to use all in one dockerfile with a matrix for building --- .github/workflows/build-images.yml | 116 ++++++++++++++++++++++++----- 1 file changed, 97 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build-images.yml b/.github/workflows/build-images.yml index 38e90fe..1c71c67 100644 --- a/.github/workflows/build-images.yml +++ b/.github/workflows/build-images.yml @@ -23,13 +23,22 @@ concurrency: jobs: build: - runs-on: ubuntu-24.04 # ubuntu-latest + name: Build ${{ matrix.target.platform }} ${{ matrix.variant }} ${{ matrix.php_version }} + runs-on: ${{ matrix.target.runner }} timeout-minutes: 10 strategy: + fail-fast: false matrix: - php_version: ['8.4', '8.3', '8.1', '8.0', '7.4'] + php_version: ['8.5' , '8.4', '8.3', '8.1', '8.0', '7.4'] variant: ['apache', 'apache-chrome'] + target: + - platform: linux/amd64 + runner: ubuntu-24.04 # ubuntu-latest + artifact_suffix: linux-amd64 + - platform: linux/arm64 + runner: ubuntu-24.04-arm # ubuntu-latest + artifact_suffix: linux-arm64 exclude: - php_version: '7.4' variant: 'apache-chrome' @@ -38,17 +47,13 @@ jobs: - name: Checkout Code uses: actions/checkout@v6 - - name: Github Short SHA - run: | - echo "GITHUB_SHA_SHORT=$(echo $GITHUB_SHA | cut -c 1-7)" >> $GITHUB_ENV - - name: Set variables run: | if [ "${{ matrix.variant }}" == "apache" ]; then - echo "DOCKER_TAG=${{ matrix.php_version }}" >> $GITHUB_ENV + echo "DOCKER_TAG=${{ github.event.number }}_${{ matrix.php_version }}" >> $GITHUB_ENV echo "DOCKER_FILE=Dockerfile" >> $GITHUB_ENV elif [ "${{ matrix.variant }}" == "apache-chrome" ]; then - echo "DOCKER_TAG=${{ matrix.php_version }}-headless" >> $GITHUB_ENV + echo "DOCKER_TAG=${{ github.event.number }}_${{ matrix.php_version }}-headless" >> $GITHUB_ENV echo "DOCKER_FILE=Dockerfile-headless" >> $GITHUB_ENV else echo "Invalid variant: ${{ matrix.variant }}" @@ -58,21 +63,94 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 - - name: Login to Docker Registry - run: echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u ${{ secrets.DOCKER_HUB_USER }} --password-stdin - - name: Login to GitHub Container Registry - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin - - name: Build and push + - name: Build and push by digest + id: build uses: docker/build-push-action@v7 with: context: . - file: ./${{ matrix.php_version }}/${{ env.DOCKER_FILE }} - tags: - ghcr.io/${{ github.repository }}:${{ env.DOCKER_TAG }}, - ghcr.io/${{ github.repository }}:${{ env.GITHUB_SHA_SHORT }} - push: true - platforms: linux/amd64,linux/arm64 + file: ./aio/${{ env.DOCKER_FILE }} + build-args: | + PHP_VERSION=${{ matrix.php_version }} + platforms: ${{ matrix.target.platform }} + outputs: type=image,name=ghcr.io/${{ github.repository }},push-by-digest=true,name-canonical=true,push=true + provenance: mode=min cache-from: type=gha cache-to: type=gha,mode=max + + - name: Export digest + run: | + mkdir -p "/tmp/digests/${{ env.DOCKER_TAG }}" + DIGEST="${{ steps.build.outputs.digest }}" + touch "/tmp/digests/${{ env.DOCKER_TAG }}/${DIGEST#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v7 + with: + name: digests-${{ env.DOCKER_TAG }}-${{ matrix.target.artifact_suffix }} + path: /tmp/digests + if-no-files-found: error + retention-days: 1 + + manifest: + name: Create multi-arch manifests + runs-on: ubuntu-24.04-arm + timeout-minutes: 10 + needs: build + + steps: + - name: Github Short SHA + run: | + echo "GITHUB_SHA_SHORT=$(echo "$GITHUB_SHA" | cut -c 1-7)" >> "$GITHUB_ENV" + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Login to Docker Registry + run: echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u ${{ secrets.DOCKER_HUB_USER }} --password-stdin + + - name: Login to GitHub Container Registry + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin + + - name: Download digests + uses: actions/download-artifact@v8 + with: + pattern: digests-* + path: /tmp/digests + merge-multiple: true + + - name: Create multi-arch manifests + run: | + set -euo pipefail + + for digest_dir in /tmp/digests/*; do + if [ ! -d "$digest_dir" ]; then + continue + fi + + docker_tag="$(basename "$digest_dir")" + digest_count="$(find "$digest_dir" -maxdepth 1 -type f | wc -l | tr -d ' ')" + + if [ "$digest_count" -lt 2 ]; then + echo "Expected at least 2 digests for ${docker_tag}, found ${digest_count}" + find "$digest_dir" -maxdepth 1 -type f -print + exit 1 + fi + + refs="" + for digest_file in "$digest_dir"/*; do + digest="$(basename "$digest_file")" + refs="${refs} ghcr.io/${{ github.repository }}@sha256:${digest}" + done + + echo "Creating manifest for ghcr.io/${{ github.repository }}:${docker_tag}" + + docker buildx imagetools create \ + -t "ghcr.io/${{ github.repository }}:${docker_tag}" \ + -t "ghcr.io/${{ github.repository }}:${GITHUB_SHA_SHORT}-${docker_tag}" \ + ${refs} + + docker buildx imagetools inspect "ghcr.io/${{ github.repository }}:${docker_tag}" + done From da0dc13534981d06344ca909308bcf1059e056b1 Mon Sep 17 00:00:00 2001 From: Noah Halstead Date: Sat, 6 Jun 2026 23:59:16 -0400 Subject: [PATCH 15/15] [skip ci] Update README.md --- README.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 3c66c34..7956683 100644 --- a/README.md +++ b/README.md @@ -2,20 +2,20 @@ ## Why -The images formed from this repo is to help minimize the extra steps needed to get up and running with a PHP Image with apache to serve traffic. All docker images are built in a CI pipeline and run every 2 days to ensure all dependencies are up-to-date with the source they are installed from. +The images formed from this repo are to help minimize the extra steps needed to get up and running with a PHP Image with apache to serve traffic. All docker images are built in a CI pipeline and run every 2 days to ensure all dependencies are up to date with the source they are installed from. -After using this docker image in other pipelines I was able to cut build times down by 4-5 minutes per build. +After using this docker image in other pipelines, I was able to cut build times down by 4-5 minutes per build. + +_Images built also support ARM/ARM64 architectures_ ## Changes -This image is the PHP 7.4 (and 8.0, 8.1) packaged with the following changes: -- PHP (version 7.4 or 8.0) +This image is the PHP+Apache Image packaged with the following changes: +- PHP (version 7.4 or 8.0–8.5) - Apache -- OPCache (and configured) +- OPCache (configured) - OpenSSL - ZIP (with libzip-dev and php extension) -- git -- iputils - Redis Extension - GD and imagick Extensions - PDO @@ -25,15 +25,16 @@ This image is the PHP 7.4 (and 8.0, 8.1) packaged with the following changes: - Apache Signatures Off - Apache Allow htaccess overrides - Apache Logs Updated to include the remote ips +- Apache Server Status (configured on :8282/healthz and :8282/server-status) --- # Images -## [Github Images](https://github.com/nhalstead/php-apache-core/pkgs/container/php-apache-core) +## [GitHub Images](https://github.com/nhalstead/php-apache-core/pkgs/container/php-apache-core) > ghcr.io/nhalstead/php-apache-core -> #### Automatically built on Wednesday +> #### Automatically built on Wednesday by GitHub Actions | PHP Version | Tag: Apache | Tag: Apache + Chrome | |:------------|:------------|:---------------------| @@ -46,7 +47,7 @@ This image is the PHP 7.4 (and 8.0, 8.1) packaged with the following changes: ## [Docker Hub Images](https://hub.docker.com/r/nhalstead00/php-apache-core) > nhalstead00/php-apache-core -> #### Automatically built every 2 days +> #### Automatically built every 2 days by CircleCI (will be replaced with GitHub Actions in the future) | PHP Version | Tag: Apache | Tag: Apache + Chrome | |:------------|:------------|:---------------------| @@ -54,5 +55,3 @@ This image is the PHP 7.4 (and 8.0, 8.1) packaged with the following changes: | 8.1 | 8.1-latest | 8.1-headless-latest | | 8.0 | 8.0-latest | 8.0-headless-latest | | 7.4 | 7.4-latest | | - -