# docker-library/php: the generated source behind the official PHP image

> The repository holds no Dockerfile per version and almost no prose. It is a template, a generator and a list of scripts that produce the php image you actually pull from Docker Hub.

**docker-library/php** — Docker Official Image packaging for PHP

- Repository: https://github.com/docker-library/php
- Website: https://php.net
- Stars: 4,040 · Forks: 2,016
- Language: Dockerfile
- License: MIT
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/docker-library-php

## Why the repository has almost no documentation

The README opens by stating it is the Git repo of the Docker Official Image for php, and it flags a confusion that catches people out: this is not an image provided by PHP upstream. It also says plainly that the full image description on Docker Hub is generated and maintained in the docker-library/docs repository, specifically in the `php` directory there.

The last line of the README explains why. It carries a comment saying the file is generated by `generate-repo-stub-readme.sh` in the docs repository. That means the README you are reading is an output, not an input. Anyone editing documentation about how to use the image is editing a different repository, and the result gets written back here mechanically.

This split has a practical consequence for anyone evaluating the project. If you arrive looking for how to install extensions or which tag to use, the useful answer is on the Docker Hub page, not here. The two other destinations the README names are the library/php label on the official-images repository for outstanding pull requests, and the `library/php` file in that repository, which it calls the current source of truth. Three repositories, one image, with a defined order of authority.

## One template file rather than a Dockerfile per version

The tree explains the design. There is a single `Dockerfile-linux.template`, and there are no Dockerfile files checked in under the version directories at all. What sits in those directories is whatever the template fills in when a build runs.

The version directories in the tree tell you the support window: `8.2/`, `8.3/`, `8.4-rc/`, `8.4/`, `8.5/` and `8.6-rc/`. Two of those carry the release candidate suffix, which is the pattern Docker official images use for a version that is not yet stable. Note that `8.4-rc/` and `8.4/` both exist, so release candidates are kept alongside the stable directory rather than being deleted once the release lands.

The generated docs README claims maintenance by the Docker Community rather than by Docker staff, and the licence on the repository is MIT. The default branch is `master`, not `main`, which is the older convention and worth knowing if you are writing automation against the raw URLs.

So the repository is best read as a small program: a template plus the scripts that fill it in, producing a family of images whose differences are the version numbers in the tags. Anyone wanting to change what goes into the image is editing the template and the scripts, not a hand-maintained Dockerfile.

## The scripts that turn a template into published images

Four shell scripts sit at the root and they map cleanly onto the pipeline. `update.sh` and `versions.sh` handle the version list, `apply-templates.sh` fills the template into the per-version directories, and `generate-stackbrew-library.sh` produces the separate library metadata Homebrew uses.

```bash
sh versions.sh
sh apply-templates.sh
```

The file that connects those scripts is `versions.json`, and the reason the repository needs `versions.sh` alongside it is that the metadata has to be reconciled against the version directories rather than being the only source. That is the kind of check that keeps an eight-entry list honest when a release candidate gets promoted.

Two things are notably absent. There is no test directory and no example application, so there is nothing here that demonstrates a working PHP container. There is also no CI configuration visible at the root beyond `.github/`. The verification that matters happens after generation, when the resulting images are built and the official image lifecycle takes over, which is the subject of the change lifecycle FAQ the README links to.

## The four docker-php scripts that ship inside the image

These are the files most PHP developers encounter first, and the confusing part is that they live in this repository's tree as plain file names because they are copied into the image rather than run from a checkout.

```bash
docker-php-ext-install
docker-php-ext-enable
docker-php-ext-configure
docker-php-source
```

`docker-php-source` handles the PHP source tree, which matters because `docker-php-ext-install` compiles extensions against it. `docker-php-ext-configure` is the layer where you can pass configure flags, which is how you get an extension built with options that are not on by default. `docker-php-ext-enable` is the step that makes an installed extension active, and skipping it is the most common reason an extension appears installed but missing at runtime.

The design point is that these are thin wrappers over the build tooling already in the base image, which means they accept the flags the underlying configure script accepts. The consequence for a reader is that the documentation for a specific extension still lives in PHP's own manual, not here. This repository provides the mechanism; the extension's own build instructions are the other half.

Because they are scripts in the image rather than commands you install, they are also the reason a plain `docker run php:8.4-cli` gives you nothing useful without a mounted application or an extension installed in a derived image.

## Web server variants and what the tags actually select

Beyond the version directories there is a single `apache2-foreground` entry in the tree, and it is the one piece of server configuration that is not generated from the template. Its name is the giveaway about how the image works: the Apache variant expects a foreground process so that the container's lifetime is tied to the web server rather than to a shell that exits immediately.

The PHP image family is therefore a version axis crossed with a server axis. A tag picks a PHP release, and a variant picks how PHP gets executed, with Apache the in-image server and FastCGI the case where an external server such as nginx or Caddy does the serving. This is the structure behind the recurring related searches for this project, where Docker-php Apache, Docker-php-fpm and Docker-php nginx all point at the same repository.

The trade-off worth naming is that the Apache variant is the easiest to start with and the least like production, because it puts the web server inside the same container as PHP. The FastCGI variant inverts that and requires you to run a second container, which is more work to set up and a closer match to how PHP is usually deployed. Neither answer is in this repository. The Docker Hub documentation covers both, and it is generated from the docs repository.

## Where to look when an image change does not appear

The README anticipates a specific confusion: you merge a change here, and the change does not show up on Docker Hub. It answers by pointing at the official images change lifecycle FAQ rather than by describing the process itself.

The answer implied by the rest of the README is that merging here is not the last step. The generated documentation lives in docker-library/docs, the accepted version list lives in the library/php file in official-images, and the build that produces the actual image runs somewhere after that. Each repository is a gate, and a change moves through them in order. The label search the README recommends is the practical way to find your own pull request once it has left this repository.

Two smaller details round out the picture. `.gitattributes` at the root and the `<!-- ... -->` HTML comment in the README are both signs of a heavily generated repository, where file attributes and boilerplate markers matter for diffing. `CONTRIBUTING.md` exists, so contribution guidance is present but it is not linked from the README, which is a reasonable place to start if you want to send a change rather than read one.

For licence questions, the repository is MIT and the README carries no additional grant. What the licence does not cover is the PHP runtime itself, which is licensed separately and is fetched from upstream during the build.

## Conclusion

This repository is worth knowing about for a specific reason: it tells you exactly which PHP versions exist as tags and which files land in the image, but it cannot tell you how to run PHP in Docker. The usage documentation lives on Docker Hub and is generated from docker-library/docs, and the authoritative version list is the library/php file in the official-images repository. Start at versions.json and the per-version directories to see what is supported, then use the four docker-php-ext scripts as your interface for adding extensions. If you need a base image with a different set of extensions and no rebuild from source, this is the wrong level to work at. The last push was on 2026-09-11 on the master branch.

## FAQ

### Can I use Docker with PHP?

The official PHP image is the supported route, and this repository is where it is built. You pick a version tag such as one of the 8.2 through 8.6 directories listed in the tree, then choose a variant for how PHP runs, with Apache in the image and FastCGI for an external web server. Usage documentation lives on the Docker Hub page rather than here.

### How can I install PHP extensions using Docker?

The image ships four scripts for this. docker-php-source prepares the PHP source, docker-php-ext-configure takes configure flags, docker-php-ext-install builds and installs an extension, and docker-php-ext-enable activates it. Forgetting the enable step is the usual reason an installed extension is missing at runtime.

### What is the latest version of Docker for PHP?

The repository's version directories at the time of the last push on 2026-09-11 ran from 8.2 through 8.5, with 8.6-rc present as a release candidate and 8.4-rc kept alongside the stable 8.4 directory. The authoritative list is the library/php file in the docker-library/official-images repository, and versions.json in this repository records the same information for the generator.

## Sources

- [docker-library/php on GitHub](https://github.com/docker-library/php)
- [Issues](https://github.com/docker-library/php/issues)
- [License: MIT](https://github.com/docker-library/php/blob/master/LICENSE)
- [Project website](https://php.net)
- [README](https://github.com/docker-library/php/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/docker-library-php
