diff --git a/.github/dependabot.yml b/.github/dependabot.yml index cb26b90..41d3cdd 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,6 +7,7 @@ updates: directories: - fpm - apache + - frankenphp schedule: interval: "daily" ignore: @@ -20,3 +21,7 @@ updates: directory: "/" schedule: interval: "daily" + groups: + specsnl-github-actions: + patterns: + - "specsnl/github-actions" diff --git a/.github/prompts/update-project.prompt.md b/.github/prompts/update-project.prompt.md new file mode 100644 index 0000000..b03dfe4 --- /dev/null +++ b/.github/prompts/update-project.prompt.md @@ -0,0 +1,211 @@ +--- +description: Safely update this project's Dockerfile dependencies and tooling in isolated commits +name: update-project +--- + +# Goal + +Perform a full dependency update across all three Dockerfile variants (fpm, apache, frankenphp) in a safe, +reproducible way. + +**Critical rule:** Any version that appears in more than one Dockerfile must be updated across all affected +Dockerfiles in a single commit. Never update a shared version in only one Dockerfile. + +If any step fails, STOP immediately and report the error. + +## Phase 1 --- Repository Safety Checks + +1. Verify the current branch is `main`. If not, abort and instruct the user to switch to `main` first. +2. Ensure the working (git) tree is clean: + - No staged changes + - No unstaged changes + - No untracked files + - If not clean: Abort immediately — inform the user to commit or stash changes. +3. Synchronize with remote: `git fetch --prune` +4. Prepare branch `updates`: + - If branch does not exist → create from `origin/main` + - If branch exists: + - If fully merged into `main` → delete locally and recreate from `origin/main`. + - If behind `main` and has NO unique commits → reset `updates` to `origin/main`. + - If it contains unique commits → abort and notify user. +5. Check if the branch does not already exist on the remote. If it does, abort and inform the user to delete +the remote branch first. + +Always branch from latest `origin/main`. + +## Phase 2 --- PHP Base Image Updates + +The three Dockerfiles use different base images but all track the same PHP 8.3.x patch series: + +- `fpm/Dockerfile`: `FROM php:-fpm-trixie` +- `apache/Dockerfile`: `FROM php:-apache-trixie` +- `frankenphp/Dockerfile`: `FROM dunglas/frankenphp:-php-trixie` + +1. Check Docker Hub for the latest `php:8.3.x-fpm-trixie` tag. Only consider patch updates within the +`8.3.x` series — do not update to a different minor or major PHP version. +2. Check Docker Hub for the latest `dunglas/frankenphp` tag that matches the pattern +`x.x.x-php8.3.x-trixie`. Only consider updates that keep the PHP 8.3.x series. +3. Update the `FROM` lines in all three Dockerfiles if newer versions are available. +4. Check `git status`. Commit all three Dockerfiles together in a single commit if there are any changes. + Commit message: `chore(deps): Update PHP base image versions`. +5. If there are no changes, skip the commit and move on. + +Abort on any failure. + +## Phase 3 --- Pie Tool Update + +All three Dockerfiles pin the same Pie version via: + +``` +COPY --from=ghcr.io/php/pie:-bin /pie /usr/bin/pie +``` + +1. Check the GitHub Releases API for the latest release of `php/pie`. +2. If a newer version is available, update the `ghcr.io/php/pie:-bin` reference in all three +Dockerfiles. +3. Check `git status`. Commit all three Dockerfiles together in a single commit if there are any changes. + Commit message: `chore(deps): Update Pie version`. +4. If there are no changes, skip the commit and move on. + +Abort on any failure. + +## Phase 4 --- PHP Runtime Extension Updates + +All three Dockerfiles share the same versions for the following PHP extensions (runtime stage ARGs): + +- `PHP_EVENT_VERSION` — `osmanov/pecl-event` on Packagist +- `PHP_IGBINARY_VERSION` — `igbinary/igbinary` on Packagist +- `PHP_REDIS_VERSION` — `phpredis/phpredis` on Packagist +- `PHP_AMQP_VERSION` — `php-amqp/php-amqp` on Packagist + +Process each extension individually and in order: + +1. Query the Packagist API for the latest stable release of the extension. +2. If a newer version is available, update the corresponding `ARG` in all three Dockerfiles. +3. Commit all three Dockerfiles together in a single commit. + Commit message: `chore(deps): Update to `. + For example: `chore(deps): Update phpredis/phpredis to 6.4.0`. +4. If there is no update for this extension, skip the commit and move on to the next extension. + +Repeat for every extension. Each updated extension gets its own commit. + +Abort on any failure. + +## Phase 5 --- Builder Stage Tool Updates + +All three Dockerfiles share the same versions for the following builder-stage tools: + +- `PHIVE_VERSION` — check the GitHub Releases API for `phar-io/phive` +- `COMPOSER_VERSION` — check `https://getcomposer.org/download/` or the GitHub Releases API for +`composer/composer` +- `XDEBUG_VERSION` — `xdebug/xdebug` on Packagist +- `PCOV_VERSION` — `pecl/pcov` on Packagist + +Process each tool individually and in order: + +1. Look up the latest stable release of the tool. +2. If a newer version is available, update the corresponding `ARG` in all three Dockerfiles. +3. Commit all three Dockerfiles together in a single commit. + Commit message: `chore(deps): Update to `. + For example: `chore(deps): Update Composer to 2.10.0`. +4. If there is no update for this tool, skip the commit and move on to the next tool. + +Repeat for every tool. Each updated tool gets its own commit. + +Abort on any failure. + +## Phase 6 --- Node.js Major Version Update + +All three Dockerfiles pin `ARG NODE_MAJOR=` for the `builder_nodejs` stage. + +1. Check the Node.js release schedule at `https://nodejs.org/en/about/previous-releases` to find the +current Active LTS major version. +2. Only update `NODE_MAJOR` if a newer **Active LTS** major version is available. Do not update to a +Current (non-LTS) release. +3. If a newer Active LTS major is available, update `NODE_MAJOR` in all three Dockerfiles. +4. Check `git status`. Commit all three Dockerfiles together in a single commit if there are any changes. + Commit message: `chore(deps): Update Node.js major version to `. +5. If there are no changes, skip the commit and move on. + +Abort on any failure. + +## Phase 7 --- Hadolint Version Update + +The `Taskfile.dist.yml` pins the Hadolint Docker image version via the `HADOLINT_TAG_VERSION` variable. + +1. Check the GitHub Releases API for the latest release of `hadolint/hadolint`. +2. If a newer version is available, update `HADOLINT_TAG_VERSION` in `Taskfile.dist.yml`. +3. Check `git status`. Commit if there are any changes. + Commit message: `chore(deps): Update Hadolint version`. +4. If there are no changes, skip the commit and move on. + +Abort on any failure. + +## Phase 8 --- GitHub Actions Updates + +1. Scan the following files for pinned `uses:` action references: + - `.github/workflows/*.yml` +2. For each external action (e.g. `specsnl/github-actions/.github/workflows/build-php.yml@1.1.1`), use +the GitHub Releases API to find the latest release tag. Check every action individually — do not assume +a version is already current. + - If the reference uses a floating major-version tag (e.g. `@v6`) and that major version is already + the latest, leave it as-is. + - If the reference is pinned to a specific semver tag (e.g. `@1.1.1`, `@v2.5.0`) and a newer version + exists, update it to the latest release tag. + - If the reference is pinned to a commit SHA, leave it as-is. +3. Update any outdated action versions in-place across all scanned files. +4. Check `git status`. Commit separately if there are any changes. + Commit message: `chore(deps): Update GitHub Actions versions`. +5. If there are no changes, skip the commit and move on. + +Abort on any failure. + +## Phase 9 --- License Year Update + +1. Check if the `LICENSE` file contains a year range (e.g. `2020-2025`) or a single year (e.g. `2024`). +2. If the current year (2026) is not already the end year: + - Single year (e.g. `2024`) → update to `2026`. + - Year range (e.g. `2020-2025`) → update the end year to `2026`. +3. Commit separately if there are any changes. + Commit message: `chore: Update copyright year`. +4. If there are no changes, skip the commit and move on. + +------------------------------------------------------------------------ + +## Final State + +Abort if there are no changes after all update steps, and inform the user that everything is already up +to date. + +- There could be up to 14 commits on the `updates` branch: + 1. PHP base image versions + 2. Pie tool version + 3. PHP runtime extension: osmanov/pecl-event + 4. PHP runtime extension: igbinary/igbinary + 5. PHP runtime extension: phpredis/phpredis + 6. PHP runtime extension: php-amqp/php-amqp + 7. Builder tool: Phive + 8. Builder tool: Composer + 9. Builder tool: Xdebug + 10. Builder tool: pcov + 11. Node.js major version + 12. Hadolint version + 13. GitHub Actions versions + 14. Copyright year +- Branch: `updates` +- Based on latest `origin/main`. +- The working tree should be clean. +- Push the branch to the remote and create a pull request for review and merging targeting `origin/main`. + The title should be `chore: Update dependencies`. +- Add a Pull Request description that lists the changes based on the commits that were made. Stick to the + commit messages but remove the "chore" prefix. For example: + +```md +Updated the following dependencies: + +- Updated PHP base image versions +- Updated Pie version +- Updated PHP runtime extension versions +- Updated builder stage tool versions +- Updated GitHub Actions versions +``` diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8a1c5c7..18557b3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,7 +15,7 @@ concurrency: jobs: build: - uses: Ilyes512/github-actions/.github/workflows/build-php.yml@1.0.12 + uses: specsnl/github-actions/.github/workflows/build-php.yml@1.1.1 strategy: fail-fast: false matrix: @@ -29,6 +29,8 @@ jobs: image-name: ghcr.io/${{ github.repository }} - dockerfile: apache/Dockerfile image-name: ghcr.io/${{ github.repository }}/apache + - dockerfile: frankenphp/Dockerfile + image-name: ghcr.io/${{ github.repository }}/frankenphp with: runs-on: ${{ matrix.runs-on.os }} platform: ${{ matrix.runs-on.platform }} @@ -36,13 +38,14 @@ jobs: dockerfile: ${{ matrix.docker.dockerfile }} merge: - uses: Ilyes512/github-actions/.github/workflows/merge-php.yml@1.0.12 + uses: specsnl/github-actions/.github/workflows/merge-php.yml@1.1.1 needs: build strategy: matrix: image-name: - ghcr.io/${{ github.repository }} - ghcr.io/${{ github.repository }}/apache + - ghcr.io/${{ github.repository }}/frankenphp with: runs-on: ubuntu-24.04 image-name: ${{ matrix.image-name }} diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f2fdaf7..2f6b1df 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -14,7 +14,7 @@ concurrency: jobs: build: - uses: Ilyes512/github-actions/.github/workflows/build-php.yml@1.0.12 + uses: specsnl/github-actions/.github/workflows/build-php.yml@1.1.1 strategy: fail-fast: false matrix: @@ -28,6 +28,8 @@ jobs: image-name: ghcr.io/${{ github.repository }} - dockerfile: apache/Dockerfile image-name: ghcr.io/${{ github.repository }}/apache + - dockerfile: frankenphp/Dockerfile + image-name: ghcr.io/${{ github.repository }}/frankenphp with: runs-on: ${{ matrix.runs-on.os }} platform: ${{ matrix.runs-on.platform }} @@ -35,13 +37,14 @@ jobs: dockerfile: ${{ matrix.docker.dockerfile }} merge: - uses: Ilyes512/github-actions/.github/workflows/merge-php.yml@1.0.12 + uses: specsnl/github-actions/.github/workflows/merge-php.yml@1.1.1 needs: build strategy: matrix: image-name: - ghcr.io/${{ github.repository }} - ghcr.io/${{ github.repository }}/apache + - ghcr.io/${{ github.repository }}/frankenphp with: runs-on: ubuntu-24.04 image-name: ${{ matrix.image-name }} diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index 5d2cc27..3c2ce0b 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -15,7 +15,7 @@ concurrency: jobs: build: - uses: Ilyes512/github-actions/.github/workflows/build-php.yml@1.0.12 + uses: specsnl/github-actions/.github/workflows/build-php.yml@1.1.1 strategy: fail-fast: false matrix: @@ -29,6 +29,8 @@ jobs: image-name: ghcr.io/${{ github.repository }} - dockerfile: apache/Dockerfile image-name: ghcr.io/${{ github.repository }}/apache + - dockerfile: frankenphp/Dockerfile + image-name: ghcr.io/${{ github.repository }}/frankenphp with: runs-on: ${{ matrix.runs-on.os }} platform: ${{ matrix.runs-on.platform }} @@ -36,13 +38,14 @@ jobs: dockerfile: ${{ matrix.docker.dockerfile }} merge: - uses: Ilyes512/github-actions/.github/workflows/merge-php.yml@1.0.12 + uses: specsnl/github-actions/.github/workflows/merge-php.yml@1.1.1 needs: build strategy: matrix: image-name: - ghcr.io/${{ github.repository }} - ghcr.io/${{ github.repository }}/apache + - ghcr.io/${{ github.repository }}/frankenphp with: runs-on: ubuntu-24.04 image-name: ${{ matrix.image-name }} diff --git a/LICENSE b/LICENSE index 4d86acf..7559929 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 Ilyes Ahidar +Copyright (c) 2026 Ilyes Ahidar Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 3ce985b..b74fdb2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Images](https://github.com/Ilyes512/php83/actions/workflows/main.yml/badge.svg)](https://github.com/Ilyes512/php83/actions/workflows/main.yml) -A PHP 8.3 (FPM and Apache) based Docker base image. +A PHP 8.3 (FPM, Apache and FrankenPHP) based Docker base image. ## Pulling the images @@ -14,6 +14,10 @@ docker pull ghcr.io/ilyes512/php83:builder_nodejs-latest docker pull ghcr.io/ilyes512/php83/apache:runtime-latest docker pull ghcr.io/ilyes512/php83/apache:builder-latest docker pull ghcr.io/ilyes512/php83/apache:builder_nodejs-latest + +docker pull ghcr.io/ilyes512/php83/frankenphp:runtime-latest +docker pull ghcr.io/ilyes512/php83/frankenphp:builder-latest +docker pull ghcr.io/ilyes512/php83/frankenphp:builder_nodejs-latest ``` The tag scheme: `{TARGET}-{VERSION}` @@ -52,11 +56,14 @@ docker build --tag ghcr.io/ilyes512/php83:builder_nodejs-latest --file fpm/Docke Available [Task](https://taskfile.dev/#/) commands: ``` -* build: Build all PHP Docker image targets of both the FPM and Apache variants +* build: Build all PHP Docker image targets of the FPM, Apache and FrankenPHP variants * build:apache: Build all PHP Docker image targets of the Apache variant * build:fpm: Build all PHP Docker image targets of the FPM variant +* build:frankenphp: Build all PHP Docker image targets of the FrankenPHP variant * lint:apache: Apply a Dockerfile linter (https://github.com/hadolint/hadolint) * lint:fpm: Apply a Dockerfile linter (https://github.com/hadolint/hadolint) +* lint:frankenphp: Apply a Dockerfile linter (https://github.com/hadolint/hadolint) * shell:apache: Interactive shell * shell:fpm: Interactive shell +* shell:frankenphp: Interactive shell ``` diff --git a/Taskfile.dist.yml b/Taskfile.dist.yml index 5c65ad7..c701519 100644 --- a/Taskfile.dist.yml +++ b/Taskfile.dist.yml @@ -14,10 +14,18 @@ silent: true tasks: build: - desc: Build all PHP Docker image targets of both the FPM and Apache variants + desc: Build all PHP Docker image targets of the FPM, Apache and FrankenPHP variants cmds: - task: build:fpm - task: build:apache + - task: build:frankenphp + + lint: + desc: Apply a Dockerfile linter to all Dockerfiles + cmds: + - task: lint:fpm + - task: lint:apache + - task: lint:frankenphp build:fpm: desc: Build all PHP Docker image targets of the FPM variant @@ -65,6 +73,29 @@ tasks: DOCKER_IMAGE_NAME: '{{.DOCKER_IMAGE_NAME}}' DOCKER_FILE_PATH: '{{.DOCKER_FILE_PATH}}' + build:frankenphp: + desc: Build all PHP Docker image targets of the FrankenPHP variant + deps: [lint:frankenphp] + vars: + DOCKER_IMAGE_NAME: php83/frankenphp + DOCKER_FILE_PATH: ./frankenphp/Dockerfile + cmds: + - task: build:target + vars: + TARGET: runtime + DOCKER_IMAGE_NAME: '{{.DOCKER_IMAGE_NAME}}' + DOCKER_FILE_PATH: '{{.DOCKER_FILE_PATH}}' + - task: build:target + vars: + TARGET: builder + DOCKER_IMAGE_NAME: '{{.DOCKER_IMAGE_NAME}}' + DOCKER_FILE_PATH: '{{.DOCKER_FILE_PATH}}' + - task: build:target + vars: + TARGET: builder_nodejs + DOCKER_IMAGE_NAME: '{{.DOCKER_IMAGE_NAME}}' + DOCKER_FILE_PATH: '{{.DOCKER_FILE_PATH}}' + build:target: preconditions: - sh: > @@ -86,16 +117,23 @@ tasks: lint:fpm: desc: Apply a Dockerfile linter (https://github.com/hadolint/hadolint) cmds: - - task: lint + - task: do:lint vars: { DOCKERFILE_PATH: fpm/Dockerfile } lint:apache: desc: Apply a Dockerfile linter (https://github.com/hadolint/hadolint) cmds: - - task: lint + - task: do:lint vars: { DOCKERFILE_PATH: apache/Dockerfile } - lint: + lint:frankenphp: + desc: Apply a Dockerfile linter (https://github.com/hadolint/hadolint) + cmds: + - task: do:lint + vars: { DOCKERFILE_PATH: frankenphp/Dockerfile } + + do:lint: + internal: true cmds: - docker run --interactive @@ -133,3 +171,16 @@ tasks: --rm {{.DOCKER_REPO}}/{{.DOCKER_OWNER}}/{{.DOCKER_IMAGE_NAME}}:builder_nodejs-{{.VERSION | default "latest" }} bash + + shell:frankenphp: + desc: Interactive shell + interactive: true + vars: + DOCKER_IMAGE_NAME: php83/frankenphp + cmds: + - docker run + --interactive + --tty + --rm + {{.DOCKER_REPO}}/{{.DOCKER_OWNER}}/{{.DOCKER_IMAGE_NAME}}:builder_nodejs-{{.VERSION | default "latest" }} + bash diff --git a/apache/Dockerfile b/apache/Dockerfile index 685774d..576d113 100644 --- a/apache/Dockerfile +++ b/apache/Dockerfile @@ -1,17 +1,25 @@ +# syntax=docker/dockerfile:1 +# check=error=true + # Latest version of PHP base image: https://hub.docker.com/_/php/tags FROM php:8.3.30-apache-trixie AS runtime -ARG UNIQUE_ID_FOR_CACHEFROM=runtime +ARG XDG_CONFIG_HOME=/config +ENV XDG_CONFIG_HOME=$XDG_CONFIG_HOME + +ARG XDG_DATA_HOME=/data +ENV XDG_DATA_HOME=$XDG_DATA_HOME + +ARG XDG_CACHE_HOME=/cache +ENV XDG_CACHE_HOME=$XDG_CACHE_HOME -# Latest version of event-extension: https://pecl.php.net/package/event -ARG PHP_EVENT_VERSION=3.1.4 -# Latest version of igbinary-extension: https://pecl.php.net/package/igbinary -ARG PHP_IGBINARY_VERSION=3.2.16 -# Latest version of redis-extension: https://pecl.php.net/package/redis +# Latest version of event-extension: https://packagist.org/packages/osmanov/pecl-event +ARG PHP_EVENT_VERSION=3.1.5 +# Latest version of igbinary-extension: https://packagist.org/packages/igbinary/igbinary +ARG PHP_IGBINARY_VERSION=3.2.17RC1 +# Latest version of redis-extension: https://packagist.org/packages/phpredis/phpredis ARG PHP_REDIS_VERSION=6.3.0 -# Latest version of memcached-extension: https://pecl.php.net/package/memcached -ARG PHP_MEMCACHED_VERSION=3.4.0 -# Latest version of amqp-extension: https://pecl.php.net/package/amqp +# Latest version of amqp-extension: https://packagist.org/packages/php-amqp/php-amqp ARG PHP_AMQP_VERSION=2.2.0 ENV SMTPHOST=mail @@ -19,6 +27,9 @@ ENV SMTPEHLO=localhost WORKDIR /var/www +# Latest version of Pie: https://github.com/php/pie/releases +COPY --from=ghcr.io/php/pie:1.3.10-bin /pie /usr/bin/pie + RUN apt-get update \ && apt-get install --assume-yes --no-install-recommends \ apt-transport-https \ @@ -26,6 +37,7 @@ RUN apt-get update \ openssl \ curl \ msmtp-mta \ + unzip \ # Dependency of the PHP intl-extension libicu76 \ # Dependency of the PHP gd-extension @@ -45,9 +57,6 @@ RUN apt-get update \ librabbitmq4 \ # Dependency of PHP xsl-extension libxslt1.1 \ - # Dependency of PHP memcached-extension - libmemcached11t64 \ - zlib1g \ # Install packages that are needed for building PHP extensions && apt-get install --assume-yes --no-install-recommends \ $PHPIZE_DEPS \ @@ -71,9 +80,6 @@ RUN apt-get update \ librabbitmq-dev \ # Dependency of PHP xsl-extension libxslt1-dev \ - # Dependency of PHP memcached-extension - libmemcached-dev \ - zlib1g-dev \ # Configure PHP gd-extension && docker-php-ext-configure gd \ --enable-gd \ @@ -94,17 +100,14 @@ RUN apt-get update \ xsl \ # Dependency of PHP event-extension sockets \ - && pecl install "event-$PHP_EVENT_VERSION" \ - # Optional dependency of PHP redis-extension - && pecl install "igbinary-$PHP_IGBINARY_VERSION" \ - && pecl install --configureoptions 'enable-redis-igbinary="yes"' "redis-$PHP_REDIS_VERSION" \ - && pecl install --configureoptions 'enable-memcached-igbinary="yes"' "memcached-$PHP_MEMCACHED_VERSION" \ - && pecl install "amqp-$PHP_AMQP_VERSION" \ + && pie install --skip-enable-extension osmanov/pecl-event:$PHP_EVENT_VERSION \ + && pie install --skip-enable-extension igbinary/igbinary:$PHP_IGBINARY_VERSION \ + && pie install --skip-enable-extension php-amqp/php-amqp:$PHP_AMQP_VERSION \ + && pie install --skip-enable-extension phpredis/phpredis:$PHP_REDIS_VERSION --enable-redis-igbinary \ && docker-php-ext-enable --ini-name docker-php-ext-zz-custom.ini \ event \ igbinary \ redis \ - memcached \ amqp \ && cp "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \ # Purge packages that where only needed for building php extensions @@ -122,10 +125,12 @@ RUN apt-get update \ libpq-dev \ librabbitmq-dev \ libxslt1-dev \ - libmemcached-dev \ - zlib1g-dev \ - # Cleanup + && mkdir -p \ + $XDG_CONFIG_HOME \ + $XDG_DATA_HOME \ + $XDG_CACHE_HOME \ && rm -rf /var/www/* \ + # Cleanup && apt-get autoremove --assume-yes \ && apt-get clean --assume-yes \ && rm -rf /var/lib/apt/lists/* \ @@ -135,15 +140,13 @@ COPY files / FROM runtime AS builder -ARG UNIQUE_ID_FOR_CACHEFROM=builder - # Latest version of Phive: https://api.github.com/repos/phar-io/phive/releases/latest ARG PHIVE_VERSION=0.16.0 # Latest version of Composer: https://getcomposer.org/download ARG COMPOSER_VERSION=2.9.5 -# Latest version of Xdebug: https://github.com/xdebug/xdebug/tags or https://pecl.php.net/package/xdebug -ARG XDEBUG_VERSION=3.5.0 -# Latest version of pcov: https://github.com/krakjoe/pcov/tags or https://pecl.php.net/package/pcov +# Latest version of Xdebug: https://packagist.org/packages/xdebug/xdebug +ARG XDEBUG_VERSION=3.5.1 +# Latest version of pcov: https://packagist.org/packages/pecl/pcov ARG PCOV_VERSION=1.0.12 RUN apt-get update \ @@ -152,9 +155,9 @@ RUN apt-get update \ $PHPIZE_DEPS \ vim \ git \ - unzip \ sqlite3 \ wait-for-it \ + p7zip-full \ # Needed for phive: gnupg \ # Install Phive @@ -167,12 +170,14 @@ RUN apt-get update \ # Install Composer using Phive && phive install --global composer:$COMPOSER_VERSION --trust-gpg-keys CBB3D576F2A0946F \ && rm -rf /root/.phive \ - # Install Xdebug PHP extension - && pecl install "xdebug-$XDEBUG_VERSION" \ - && docker-php-ext-enable xdebug \ - # Install pcov PHP extension - && pecl install "pcov-$PCOV_VERSION" \ - && docker-php-ext-enable pcov \ + # Download Composer keys + && mkdir -p "$XDG_CONFIG_HOME/composer" \ + && curl -fsSLo "$XDG_CONFIG_HOME/composer/keys.dev.pub" https://composer.github.io/snapshots.pub \ + && curl -fsSLo "$XDG_CONFIG_HOME/composer/keys.tags.pub" https://composer.github.io/releases.pub \ + && chmod 644 "$XDG_CONFIG_HOME/composer/keys.dev.pub" "$XDG_CONFIG_HOME/composer/keys.tags.pub" \ + # Install Xdebug and pcov PHP extensions + && pie install xdebug/xdebug:$XDEBUG_VERSION \ + && pie install pecl/pcov:$PCOV_VERSION \ && cp "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" \ # Cleanup && apt-get purge --assume-yes $PHPIZE_DEPS \ @@ -187,8 +192,6 @@ ARG TARGETARCH SHELL ["/bin/bash", "-o", "pipefail", "-c"] -ARG UNIQUE_ID_FOR_CACHEFROM=builder_nodejs - # Latest version of Node.js: https://nodejs.org ARG NODE_MAJOR=24 @@ -210,6 +213,7 @@ RUN apt-get update \ && npm uninstall --global npm \ && corepack install --global npm@11.x yarn@4.x pnpm@10.x \ && corepack enable npm yarn pnpm \ + # Cleanup && apt-get autoremove --assume-yes \ && apt-get clean --assume-yes \ && rm -rf /var/lib/apt/lists/* \ diff --git a/files/etc/frankenphp/Caddyfile b/files/etc/frankenphp/Caddyfile new file mode 100644 index 0000000..0179361 --- /dev/null +++ b/files/etc/frankenphp/Caddyfile @@ -0,0 +1,41 @@ +# FrankenPHP Caddyfile +# Documentation: https://frankenphp.dev/docs/config/ +# +# Environment variables: +# - SERVER_NAME: Change the addresses to listen on (default: localhost) +# - SERVER_ROOT: Change the root directory (default: public/) +# - CADDY_GLOBAL_OPTIONS: Inject global options (e.g., "debug" for debug mode) +# - FRANKENPHP_CONFIG: Inject FrankenPHP config (e.g., "worker /var/www/public/index.php" for worker mode) +# - CADDY_SERVER_EXTRA_DIRECTIVES: Inject additional server-level directives +# +# Classic mode (default): No additional configuration needed +# Worker mode: Set FRANKENPHP_CONFIG="worker /var/www/public/index.php" + +{ + {$CADDY_GLOBAL_OPTIONS} + + frankenphp { + {$FRANKENPHP_CONFIG} + } +} + +{$SERVER_NAME:localhost} { + # Access logging (JSON format, outputs to stdout) + log { + format json + } + + root * {$SERVER_ROOT:/var/www/public} + + # Enable compression + encode zstd br gzip + + # Execute PHP files and serve assets + php_server + + # Extra directives + {$CADDY_SERVER_EXTRA_DIRECTIVES} +} + +# Import custom Caddyfile fragments +import Caddyfile.d/*.caddyfile diff --git a/fpm/Dockerfile b/fpm/Dockerfile index 844262e..0dbecf5 100644 --- a/fpm/Dockerfile +++ b/fpm/Dockerfile @@ -1,17 +1,25 @@ +# syntax=docker/dockerfile:1 +# check=error=true + # Latest version of PHP base image: https://hub.docker.com/_/php/tags FROM php:8.3.30-fpm-trixie AS runtime -ARG UNIQUE_ID_FOR_CACHEFROM=runtime +ARG XDG_CONFIG_HOME=/config +ENV XDG_CONFIG_HOME=$XDG_CONFIG_HOME + +ARG XDG_DATA_HOME=/data +ENV XDG_DATA_HOME=$XDG_DATA_HOME + +ARG XDG_CACHE_HOME=/cache +ENV XDG_CACHE_HOME=$XDG_CACHE_HOME -# Latest version of event-extension: https://pecl.php.net/package/event -ARG PHP_EVENT_VERSION=3.1.4 -# Latest version of igbinary-extension: https://pecl.php.net/package/igbinary -ARG PHP_IGBINARY_VERSION=3.2.16 -# Latest version of redis-extension: https://pecl.php.net/package/redis +# Latest version of event-extension: https://packagist.org/packages/osmanov/pecl-event +ARG PHP_EVENT_VERSION=3.1.5 +# Latest version of igbinary-extension: https://packagist.org/packages/igbinary/igbinary +ARG PHP_IGBINARY_VERSION=3.2.17RC1 +# Latest version of redis-extension: https://packagist.org/packages/phpredis/phpredis ARG PHP_REDIS_VERSION=6.3.0 -# Latest version of memcached-extension: https://pecl.php.net/package/memcached -ARG PHP_MEMCACHED_VERSION=3.4.0 -# Latest version of amqp-extension: https://pecl.php.net/package/amqp +# Latest version of amqp-extension: https://packagist.org/packages/php-amqp/php-amqp ARG PHP_AMQP_VERSION=2.2.0 ENV SMTPHOST=mail @@ -19,6 +27,9 @@ ENV SMTPEHLO=localhost WORKDIR /var/www +# Latest version of Pie: https://github.com/php/pie/releases +COPY --from=ghcr.io/php/pie:1.3.10-bin /pie /usr/bin/pie + RUN apt-get update \ && apt-get install --assume-yes --no-install-recommends \ apt-transport-https \ @@ -26,6 +37,7 @@ RUN apt-get update \ openssl \ curl \ msmtp-mta \ + unzip \ # Dependency of the PHP intl-extension libicu76 \ # Dependency of the PHP gd-extension @@ -45,9 +57,6 @@ RUN apt-get update \ librabbitmq4 \ # Dependency of PHP xsl-extension libxslt1.1 \ - # Dependency of PHP memcached-extension - libmemcached11t64 \ - zlib1g \ # Install packages that are needed for building PHP extensions && apt-get install --assume-yes --no-install-recommends \ $PHPIZE_DEPS \ @@ -71,9 +80,6 @@ RUN apt-get update \ librabbitmq-dev \ # Dependency of PHP xsl-extension libxslt1-dev \ - # Dependency of PHP memcached-extension - libmemcached-dev \ - zlib1g-dev \ # Configure PHP gd-extension && docker-php-ext-configure gd \ --enable-gd \ @@ -94,17 +100,14 @@ RUN apt-get update \ xsl \ # Dependency of PHP event-extension sockets \ - && pecl install "event-$PHP_EVENT_VERSION" \ - # Optional dependency of PHP redis-extension - && pecl install "igbinary-$PHP_IGBINARY_VERSION" \ - && pecl install --configureoptions 'enable-redis-igbinary="yes"' "redis-$PHP_REDIS_VERSION" \ - && pecl install --configureoptions 'enable-memcached-igbinary="yes"' "memcached-$PHP_MEMCACHED_VERSION" \ - && pecl install "amqp-$PHP_AMQP_VERSION" \ + && pie install --skip-enable-extension osmanov/pecl-event:$PHP_EVENT_VERSION \ + && pie install --skip-enable-extension igbinary/igbinary:$PHP_IGBINARY_VERSION \ + && pie install --skip-enable-extension php-amqp/php-amqp:$PHP_AMQP_VERSION \ + && pie install --skip-enable-extension phpredis/phpredis:$PHP_REDIS_VERSION --enable-redis-igbinary \ && docker-php-ext-enable --ini-name docker-php-ext-zz-custom.ini \ event \ igbinary \ redis \ - memcached \ amqp \ && cp "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \ # Purge packages that where only needed for building php extensions @@ -122,10 +125,12 @@ RUN apt-get update \ libpq-dev \ librabbitmq-dev \ libxslt1-dev \ - libmemcached-dev \ - zlib1g-dev \ - # Cleanup + && mkdir -p \ + $XDG_CONFIG_HOME \ + $XDG_DATA_HOME \ + $XDG_CACHE_HOME \ && rm -rf /var/www/* \ + # Cleanup && apt-get autoremove --assume-yes \ && apt-get clean --assume-yes \ && rm -rf /var/lib/apt/lists/* \ @@ -135,15 +140,13 @@ COPY files / FROM runtime AS builder -ARG UNIQUE_ID_FOR_CACHEFROM=builder - # Latest version of Phive: https://api.github.com/repos/phar-io/phive/releases/latest ARG PHIVE_VERSION=0.16.0 # Latest version of Composer: https://getcomposer.org/download ARG COMPOSER_VERSION=2.9.5 -# Latest version of Xdebug: https://github.com/xdebug/xdebug/tags or https://pecl.php.net/package/xdebug -ARG XDEBUG_VERSION=3.5.0 -# Latest version of pcov: https://github.com/krakjoe/pcov/tags or https://pecl.php.net/package/pcov +# Latest version of Xdebug: https://packagist.org/packages/xdebug/xdebug +ARG XDEBUG_VERSION=3.5.1 +# Latest version of pcov: https://packagist.org/packages/pecl/pcov ARG PCOV_VERSION=1.0.12 RUN apt-get update \ @@ -152,9 +155,9 @@ RUN apt-get update \ $PHPIZE_DEPS \ vim \ git \ - unzip \ sqlite3 \ wait-for-it \ + p7zip-full \ # Needed for phive: gnupg \ # Install Phive @@ -167,12 +170,14 @@ RUN apt-get update \ # Install Composer using Phive && phive install --global composer:$COMPOSER_VERSION --trust-gpg-keys CBB3D576F2A0946F \ && rm -rf /root/.phive \ - # Install Xdebug PHP extension - && pecl install "xdebug-$XDEBUG_VERSION" \ - && docker-php-ext-enable xdebug \ - # Install pcov PHP extension - && pecl install "pcov-$PCOV_VERSION" \ - && docker-php-ext-enable pcov \ + # Download Composer keys + && mkdir -p "$XDG_CONFIG_HOME/composer" \ + && curl -fsSLo "$XDG_CONFIG_HOME/composer/keys.dev.pub" https://composer.github.io/snapshots.pub \ + && curl -fsSLo "$XDG_CONFIG_HOME/composer/keys.tags.pub" https://composer.github.io/releases.pub \ + && chmod 644 "$XDG_CONFIG_HOME/composer/keys.dev.pub" "$XDG_CONFIG_HOME/composer/keys.tags.pub" \ + # Install Xdebug and pcov PHP extensions + && pie install xdebug/xdebug:$XDEBUG_VERSION \ + && pie install pecl/pcov:$PCOV_VERSION \ && cp "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" \ # Cleanup && apt-get purge --assume-yes $PHPIZE_DEPS \ @@ -187,8 +192,6 @@ ARG TARGETARCH SHELL ["/bin/bash", "-o", "pipefail", "-c"] -ARG UNIQUE_ID_FOR_CACHEFROM=builder_nodejs - # Latest version of Node.js: https://nodejs.org ARG NODE_MAJOR=24 @@ -210,6 +213,7 @@ RUN apt-get update \ && npm uninstall --global npm \ && corepack install --global npm@11.x yarn@4.x pnpm@10.x \ && corepack enable npm yarn pnpm \ + # Cleanup && apt-get autoremove --assume-yes \ && apt-get clean --assume-yes \ && rm -rf /var/lib/apt/lists/* \ diff --git a/frankenphp/Dockerfile b/frankenphp/Dockerfile new file mode 100644 index 0000000..2780d78 --- /dev/null +++ b/frankenphp/Dockerfile @@ -0,0 +1,224 @@ +# syntax=docker/dockerfile:1 +# check=error=true + +# Latest version of FrankenPHP base image: https://hub.docker.com/r/dunglas/frankenphp/tags +FROM dunglas/frankenphp:1.12.1-php8.3-trixie AS runtime + +ARG XDG_CONFIG_HOME=/config +ENV XDG_CONFIG_HOME=$XDG_CONFIG_HOME + +ARG XDG_DATA_HOME=/data +ENV XDG_DATA_HOME=$XDG_DATA_HOME + +ARG XDG_CACHE_HOME=/cache +ENV XDG_CACHE_HOME=$XDG_CACHE_HOME + +# Latest version of event-extension: https://packagist.org/packages/osmanov/pecl-event +ARG PHP_EVENT_VERSION=3.1.5 +# Latest version of igbinary-extension: https://packagist.org/packages/igbinary/igbinary +ARG PHP_IGBINARY_VERSION=3.2.17RC1 +# Latest version of redis-extension: https://packagist.org/packages/phpredis/phpredis +ARG PHP_REDIS_VERSION=6.3.0 +# Latest version of amqp-extension: https://packagist.org/packages/php-amqp/php-amqp +ARG PHP_AMQP_VERSION=2.2.0 + +ENV SMTPHOST=mail +ENV SMTPEHLO=localhost + +# Default to classic mode (no workers). To enable worker mode, set: +# FRANKENPHP_CONFIG="worker /var/www/public/index.php" +ENV FRANKENPHP_CONFIG="" + +WORKDIR /var/www + +# Latest version of Pie: https://github.com/php/pie/releases +COPY --from=ghcr.io/php/pie:1.3.10-bin /pie /usr/bin/pie + +RUN apt-get update \ + && apt-get install --assume-yes --no-install-recommends \ + apt-transport-https \ + ca-certificates \ + openssl \ + curl \ + msmtp-mta \ + unzip \ + # Dependency of the PHP intl-extension + libicu76 \ + # Dependency of the PHP gd-extension + libpng16-16t64 \ + libwebp7 \ + libjpeg62-turbo \ + libfreetype6 \ + # Dependency of PHP zip-extension + libzip5 \ + # Dependency of PHP event-extension + libevent-2.1-7t64 \ + libevent-openssl-2.1-7t64 \ + libevent-extra-2.1-7t64 \ + # Dependency of PHP pdo_pgsql-extension + libpq5 \ + # Dependency of PHP amqp-extension + librabbitmq4 \ + # Dependency of PHP xsl-extension + libxslt1.1 \ + # Install packages that are needed for building PHP extensions + && apt-get install --assume-yes --no-install-recommends \ + $PHPIZE_DEPS \ + # Dependency of the PHP intl-extension + libicu-dev \ + # Dependencies of PHP gd-extension + libpng-dev \ + libwebp-dev \ + libjpeg62-turbo-dev \ + libfreetype6-dev \ + # Dependency of PHP zip-extension + libzip-dev \ + # Dependency of PHP event-extension + libevent-dev \ + libssl-dev \ + # Dependency of PHP soap-extension + libxml2-dev \ + # Dependency of PHP pdo_pgsql-extension + libpq-dev \ + # Dependency of PHP amqp-extension + librabbitmq-dev \ + # Dependency of PHP xsl-extension + libxslt1-dev \ + # Configure PHP gd-extension + && docker-php-ext-configure gd \ + --enable-gd \ + --with-jpeg \ + --with-freetype \ + --with-webp \ + # Install PHP extensions + && docker-php-ext-install -j "$(nproc --all)" \ + pdo_mysql \ + pdo_pgsql \ + intl \ + opcache \ + pcntl \ + gd \ + bcmath \ + zip \ + soap \ + xsl \ + # Dependency of PHP event-extension + sockets \ + && pie install --skip-enable-extension osmanov/pecl-event:$PHP_EVENT_VERSION \ + && pie install --skip-enable-extension igbinary/igbinary:$PHP_IGBINARY_VERSION \ + && pie install --skip-enable-extension php-amqp/php-amqp:$PHP_AMQP_VERSION \ + && pie install --skip-enable-extension phpredis/phpredis:$PHP_REDIS_VERSION --enable-redis-igbinary \ + && docker-php-ext-enable --ini-name docker-php-ext-zz-custom.ini \ + event \ + igbinary \ + redis \ + amqp \ + && cp "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \ + # Purge packages that where only needed for building php extensions + && apt-get purge --assume-yes \ + $PHPIZE_DEPS \ + libicu-dev \ + libpng-dev \ + libwebp-dev \ + libjpeg62-turbo-dev \ + libfreetype6-dev \ + libzip-dev \ + libevent-dev \ + libssl-dev \ + libxml2-dev \ + libpq-dev \ + librabbitmq-dev \ + libxslt1-dev \ + && mkdir -p \ + $XDG_CONFIG_HOME \ + $XDG_DATA_HOME \ + $XDG_CACHE_HOME \ + && rm -rf /var/www/* \ + # Cleanup + && apt-get autoremove --assume-yes \ + && apt-get clean --assume-yes \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/* + +COPY files / + +FROM runtime AS builder + +# Latest version of Phive: https://api.github.com/repos/phar-io/phive/releases/latest +ARG PHIVE_VERSION=0.16.0 +# Latest version of Composer: https://getcomposer.org/download +ARG COMPOSER_VERSION=2.9.5 +# Latest version of Xdebug: https://packagist.org/packages/xdebug/xdebug +ARG XDEBUG_VERSION=3.5.1 +# Latest version of pcov: https://packagist.org/packages/pecl/pcov +ARG PCOV_VERSION=1.0.12 + +RUN apt-get update \ + && apt-get install --assume-yes --no-install-recommends \ + # Needed for xdebug extension configuration + $PHPIZE_DEPS \ + vim \ + git \ + sqlite3 \ + wait-for-it \ + p7zip-full \ + # Needed for phive: + gnupg \ + # Install Phive + && curl -fsSLo /usr/local/bin/phive "https://github.com/phar-io/phive/releases/download/$PHIVE_VERSION/phive-$PHIVE_VERSION.phar" \ + && curl -fsSLo /tmp/phive.phar.asc "https://github.com/phar-io/phive/releases/download/$PHIVE_VERSION/phive-$PHIVE_VERSION.phar.asc" \ + && gpg --keyserver keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79 \ + && gpg --verify /tmp/phive.phar.asc /usr/local/bin/phive \ + && chmod +x /usr/local/bin/phive \ + && phive update-repository-list \ + # Install Composer using Phive + && phive install --global composer:$COMPOSER_VERSION --trust-gpg-keys CBB3D576F2A0946F \ + && rm -rf /root/.phive \ + # Download Composer keys + && mkdir -p "$XDG_CONFIG_HOME/composer" \ + && curl -fsSLo "$XDG_CONFIG_HOME/composer/keys.dev.pub" https://composer.github.io/snapshots.pub \ + && curl -fsSLo "$XDG_CONFIG_HOME/composer/keys.tags.pub" https://composer.github.io/releases.pub \ + && chmod 644 "$XDG_CONFIG_HOME/composer/keys.dev.pub" "$XDG_CONFIG_HOME/composer/keys.tags.pub" \ + # Install Xdebug and pcov PHP extensions + && pie install xdebug/xdebug:$XDEBUG_VERSION \ + && pie install pecl/pcov:$PCOV_VERSION \ + && cp "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" \ + # Cleanup + && apt-get purge --assume-yes $PHPIZE_DEPS \ + && apt-get autoremove --assume-yes \ + && apt-get clean --assume-yes \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/* + +FROM builder AS builder_nodejs + +ARG TARGETARCH + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +# Latest version of Node.js: https://nodejs.org +ARG NODE_MAJOR=24 + +RUN apt-get update \ + && apt-get install --assume-yes --no-install-recommends \ + gcc \ + g++ \ + make \ + && mkdir -p /usr/share/keyrings \ + && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /usr/share/keyrings/nodesource.gpg \ + && chmod 644 /usr/share/keyrings/nodesource.gpg \ + && echo "deb [arch=$TARGETARCH signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list \ + && echo "Package: nodejs" | tee /etc/apt/preferences.d/nodejs > /dev/null \ + && echo "Pin: origin deb.nodesource.com" | tee -a /etc/apt/preferences.d/nodejs > /dev/null \ + && echo "Pin-Priority: 600" | tee -a /etc/apt/preferences.d/nodejs > /dev/null \ + && apt-get update \ + && apt-get install --assume-yes --no-install-recommends \ + nodejs \ + && npm uninstall --global npm \ + && corepack install --global npm@11.x yarn@4.x pnpm@10.x \ + && corepack enable npm yarn pnpm \ + # Cleanup + && apt-get autoremove --assume-yes \ + && apt-get clean --assume-yes \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/*