From 57eaa5f2ca4c8dadc733ad538a161b6891268c2a Mon Sep 17 00:00:00 2001 From: Matthias Vogel Date: Wed, 11 Nov 2026 06:47:58 +0000 Subject: [PATCH] [TASK] Move the build documentation from README.md to CONTRIBUTING.md README.md is the entry point for the users of the images. How the files of this repository are generated and how the images are built, checked and tested moves to CONTRIBUTING.md without a change of content; only the two references to the README become links. GitHub links the file on the pages for a new issue and a new pull request. README.md keeps the heading "Build process" with a link to the new file, so links to it still lead there. AGENTS.md lists CONTRIBUTING.md among the documentation, and docs/README.md links to it. --- AGENTS.md | 5 ++- CONTRIBUTING.md | 97 +++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 93 +---------------------------------------------- docs/README.md | 2 +- 4 files changed, 102 insertions(+), 95 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/AGENTS.md b/AGENTS.md index 696ed27ac..7ec60c36a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -47,7 +47,8 @@ Where the documentation lives: | File | Content | | --- | --- | -| `README.md` | Entry point: short intro, quick start, build process, supported tags ("Debian PHP" / "Alpine PHP") | +| `README.md` | Entry point: short intro, quick start, supported tags ("Debian PHP" / "Alpine PHP") | +| `CONTRIBUTING.md` | Build process: the generated files and `make generate`, the CI and `make check`, building and testing locally, PHP extension builds | | `docs/README.md` | Image overview, platforms and nightly updates, how the images build on each other (Mermaid diagram) | | `docs/environment-variables.md` | Every environment variable with its default and effect; uploads and long requests | | `docs/customization.md` | Commands, scripts at start and build time, tools for your Dockerfile, services, cron jobs and their time zone, healthcheck, configuration files and placeholders, supervisord, locales, application user and changing its UID | @@ -64,7 +65,7 @@ Update the documentation whenever a change touches any of these: - a base image or operating system version - a PHP extension that is added or removed - a service, hook directory, entrypoint command or helper tool such as `docker-service` -- the build process, the CI workflow or the commands in the README +- the build process, the CI workflow or the commands in `CONTRIBUTING.md` ### How to update it diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..d24df642a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,97 @@ +# Contributing + +How the files in this repository are generated, and how the images are built and tested. +How to use the images is described in the [README](README.md) and the [documentation](docs/README.md). + +## File generation + +The files inside the `docker` directory, the GitHub Actions workflow (`.github/workflows/build.yaml`) and the banner at the top of the [README](README.md) are generated with PHP: + +``` +make generate +``` + +It installs the PHP tools of `ci/` with Composer and runs `ci/console generate` in `webdevops/php:8.4-alpine`, so you only need `make` and Docker. +The container runs as your user, so the files it writes belong to you. +`ci/console generate` runs these commands in this order; each of them also runs on its own: + +| Command | Writes | +| --- | --- | +| `ci/console generate:dockerfile` | `docker///Dockerfile` from the `Dockerfile.twig` next to it and the Twig templates in the `template` directory, and the links `docker/php/` to `docker/php-official/` | +| `ci/console generate:provision` | `docker///conf/` from the `provisioning` directory, as configured in `conf/provision.yml` | +| `ci/console generate:github-ci` | `.github/workflows/build.yaml`, a build and a publish job for every Dockerfile | +| `ci/console generate:readme-banner` | `docs/assets/readme-banner-*.svg` | + +**The generated files are never modified manually.** +Edit the `Dockerfile.twig` templates, the shared templates in `template`, the files in `provisioning` or the settings in `conf` instead. +`template/Dockerfile/layout.twig` writes the header of every Dockerfile and includes its `Dockerfile.twig`. +A `Dockerfile.twig` imports the macros it uses from `template/Dockerfile`, e.g. `{% import 'docker.twig' as docker %}`; a macro imports the macros it calls itself. +`generate:provision` empties the `conf/` directories of an image first, so a file removed from `provisioning` disappears there too. +It checks all of `conf/provision.yml` before it changes a file and stops if a source directory or a tag does not exist, or if an image has another setting than `configuration`. +`generate:dockerfile` stops if a directory `docker//` has files but no `Dockerfile.twig`; it first removes the `.DS_Store` files of the macOS Finder under `docker`. +To stop building a tag, remove its directory and those of the tags that build on it; `generate:github-ci` names any it finds. `generate:dockerfile` adds and removes the links in `docker/php` along with the `php-official` tags. + +## Building in CI + +The banner (`docs/assets/readme-banner-*.svg`) takes the PHP versions, web servers, base OS suffixes, Debian releases and platforms from the images that are built. +Its texts are in `conf/readme-banner.yml`. The CI fails if a generated file is out of date or missing. + +The PHP code in `ci/` follows the rules of [pluswerk/grumphp-config](https://github.com/andersundsehr/grumphp-config) (PSR-12, PHPStan level 8, Rector, `composer audit`) and has PHPUnit tests in `ci/tests`. +GrumPHP runs all of them; after a change to `ci/`, run it with: + +``` +make check +``` + +It installs the PHP tools of `ci/` and runs GrumPHP as your user. `make test` runs only the PHPUnit tests. + +The CI job "Check ci/" runs the same checks. No image build waits for it. + +GitHub Actions builds every image independently and runs the serverspec and structure tests +defined for it before pushing it to Docker Hub. The CI also uses `ghcr.io/webdevops/`, but only +internally; pull the images from Docker Hub. + +## Building and testing locally + +Build a single image from its directory. Its parent image (the `FROM` line) and `webdevops/toolbox` are taken from your local images or pulled from Docker Hub: + +``` +docker build -t webdevops/php-nginx:8.5 docker/php-nginx/8.5 +``` + +Build all PHP images of one version (default `8.5`), in the order they depend on each other: + +``` +./build-local.sh 8.4 +``` + +Then try an image with the [quick start](README.md#quick-start). + +The CI runs the serverspec tests for every image except `toolbox` and `dockerfile-build-env`, and the structure tests for `bootstrap`, `base`, `base-app`, `php`, `php-dev` and `php-nginx`. +To run the structure tests against the images you built locally: + +``` +docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v $PWD:/app -w /app webdevops/dockerfile-build-env make structure-test +``` + +It tests the local tags that the CI builds and fails if no such image exists. + +## PHP extension builds + +PHP images require Docker BuildKit. The official `ghcr.io/php/pie:bin` image +supplies PIE through a build-only mount; the existing INI configuration still +controls extension loading. PIE requests remain unpinned, and compilation uses +`nproc` parallel jobs. + +Protobuf, Vips and XML-RPC are built directly from their official upstream sources. +The existing XML-RPC **1.0.0RC3** pin is preserved on all supported PHP versions. +Protobuf on PHP 8.2–8.5 uses the latest upstream release. If a future release raises its minimum PHP +version, older PHP image builds can fail; there is no automatic fallback to an +older release. The existing CI matrix checks compatibility across PHP versions. + +The native Vips extension is deprecated and no longer maintained upstream. It is +retained for existing applications, using the upstream default branch (currently +`master`): GitHub tags predate the PECL 1.0.13 release and would downgrade the +extension. This includes changes beyond the last PECL release. +No extension installation needs `pecl.php.net`; Serverspec and container structure +tests retain their existing image matrix. diff --git a/README.md b/README.md index d82f3f5a0..1c6726b96 100644 --- a/README.md +++ b/README.md @@ -43,98 +43,7 @@ Or join our discord https://discord.gg/BpBZtXAgJz ## Build process -### File generation - -The files inside the `docker` directory, the GitHub Actions workflow (`.github/workflows/build.yaml`) and the banner at the top of this README are generated with PHP: - -``` -make generate -``` - -It installs the PHP tools of `ci/` with Composer and runs `ci/console generate` in `webdevops/php:8.4-alpine`, so you only need `make` and Docker. -The container runs as your user, so the files it writes belong to you. -`ci/console generate` runs these commands in this order; each of them also runs on its own: - -| Command | Writes | -| --- | --- | -| `ci/console generate:dockerfile` | `docker///Dockerfile` from the `Dockerfile.twig` next to it and the Twig templates in the `template` directory, and the links `docker/php/` to `docker/php-official/` | -| `ci/console generate:provision` | `docker///conf/` from the `provisioning` directory, as configured in `conf/provision.yml` | -| `ci/console generate:github-ci` | `.github/workflows/build.yaml`, a build and a publish job for every Dockerfile | -| `ci/console generate:readme-banner` | `docs/assets/readme-banner-*.svg` | - -**The generated files are never modified manually.** -Edit the `Dockerfile.twig` templates, the shared templates in `template`, the files in `provisioning` or the settings in `conf` instead. -`template/Dockerfile/layout.twig` writes the header of every Dockerfile and includes its `Dockerfile.twig`. -A `Dockerfile.twig` imports the macros it uses from `template/Dockerfile`, e.g. `{% import 'docker.twig' as docker %}`; a macro imports the macros it calls itself. -`generate:provision` empties the `conf/` directories of an image first, so a file removed from `provisioning` disappears there too. -It checks all of `conf/provision.yml` before it changes a file and stops if a source directory or a tag does not exist, or if an image has another setting than `configuration`. -`generate:dockerfile` stops if a directory `docker//` has files but no `Dockerfile.twig`; it first removes the `.DS_Store` files of the macOS Finder under `docker`. -To stop building a tag, remove its directory and those of the tags that build on it; `generate:github-ci` names any it finds. `generate:dockerfile` adds and removes the links in `docker/php` along with the `php-official` tags. - -### Building in CI - -The banner (`docs/assets/readme-banner-*.svg`) takes the PHP versions, web servers, base OS suffixes, Debian releases and platforms from the images that are built. -Its texts are in `conf/readme-banner.yml`. The CI fails if a generated file is out of date or missing. - -The PHP code in `ci/` follows the rules of [pluswerk/grumphp-config](https://github.com/andersundsehr/grumphp-config) (PSR-12, PHPStan level 8, Rector, `composer audit`) and has PHPUnit tests in `ci/tests`. -GrumPHP runs all of them; after a change to `ci/`, run it with: - -``` -make check -``` - -It installs the PHP tools of `ci/` and runs GrumPHP as your user. `make test` runs only the PHPUnit tests. - -The CI job "Check ci/" runs the same checks. No image build waits for it. - -GitHub Actions builds every image independently and runs the serverspec and structure tests -defined for it before pushing it to Docker Hub. The CI also uses `ghcr.io/webdevops/`, but only -internally; pull the images from Docker Hub. - -### Building and testing locally - -Build a single image from its directory. Its parent image (the `FROM` line) and `webdevops/toolbox` are taken from your local images or pulled from Docker Hub: - -``` -docker build -t webdevops/php-nginx:8.5 docker/php-nginx/8.5 -``` - -Build all PHP images of one version (default `8.5`), in the order they depend on each other: - -``` -./build-local.sh 8.4 -``` - -Then try an image with the quick start above. - -The CI runs the serverspec tests for every image except `toolbox` and `dockerfile-build-env`, and the structure tests for `bootstrap`, `base`, `base-app`, `php`, `php-dev` and `php-nginx`. -To run the structure tests against the images you built locally: - -``` -docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v $PWD:/app -w /app webdevops/dockerfile-build-env make structure-test -``` - -It tests the local tags that the CI builds and fails if no such image exists. - -### PHP extension builds - -PHP images require Docker BuildKit. The official `ghcr.io/php/pie:bin` image -supplies PIE through a build-only mount; the existing INI configuration still -controls extension loading. PIE requests remain unpinned, and compilation uses -`nproc` parallel jobs. - -Protobuf, Vips and XML-RPC are built directly from their official upstream sources. -The existing XML-RPC **1.0.0RC3** pin is preserved on all supported PHP versions. -Protobuf on PHP 8.2–8.5 uses the latest upstream release. If a future release raises its minimum PHP -version, older PHP image builds can fail; there is no automatic fallback to an -older release. The existing CI matrix checks compatibility across PHP versions. - -The native Vips extension is deprecated and no longer maintained upstream. It is -retained for existing applications, using the upstream default branch (currently -`master`): GitHub tags predate the PECL 1.0.13 release and would downgrade the -extension. This includes changes beyond the last PECL release. -No extension installation needs `pecl.php.net`; Serverspec and container structure -tests retain their existing image matrix. +How the files in this repository are generated, and how the images are built and tested, is described in [CONTRIBUTING.md](CONTRIBUTING.md). ## Documentation diff --git a/docs/README.md b/docs/README.md index 5aa965623..5a1a3cde1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,7 +13,7 @@ Documentation for the `webdevops/*` Docker images. It describes the images as th | [`webdevops/apache`](images/apache.md) | Apache without PHP | | [`webdevops/bootstrap`, `webdevops/base`, `webdevops/base-app`](images/base.md) | Base images for your own images | | `webdevops/toolbox` | Build helper, not meant to run. Stores the baselayout scripts (`apt-install`, `apk-install`, `docker-image-cleanup`, `docker-run-bootstrap`, `generate-locales` and more), `go-replace` and `gosu` under `/baselayout`. `bootstrap` and `php` copy them from there with `COPY --from=webdevops/toolbox`. In `toolbox` itself only `go-replace` is on the `PATH`. | -| `webdevops/dockerfile-build-env` | Build environment for this repository, based on `base-app:ubuntu-22.04`. The CI runs the serverspec and structure tests in it, see [Build process](../README.md#build-process). | +| `webdevops/dockerfile-build-env` | Build environment for this repository, based on `base-app:ubuntu-22.04`. The CI runs the serverspec and structure tests in it, see [Building in CI](../CONTRIBUTING.md#building-in-ci). | `webdevops/storage`, `webdevops/vsftp` and `webdevops/ssh` are no longer built. [Replacing discontinued images](discontinued-images.md) shows what to use instead.