Skip to content

Build PHP from source so security releases don't wait on Docker Hub - #728

Draft
jaydrogers wants to merge 8 commits into
mainfrom
build-from-source
Draft

jaydrogers wants to merge 8 commits into
mainfrom
build-from-source

Conversation

@jaydrogers

Copy link
Copy Markdown
Member

What

This is a draft to test the plan from #727 in CI before we commit to it. We compile PHP ourselves from php.net into serversideup/php-base and build every image on it, so a PHP security release no longer waits on Docker Hub.

Why

For the PHP2Shell fix, our images went live 4 hours and 20 minutes after php.net published the source. Our own build took 27 minutes. The rest was waiting on the official images, PECL, and a one-off v4 workflow.

What changes

  • PHP from source. php-base renders docker-library's own template, vendored unchanged in src/base/upstream. Our only changes are five small patches in scripts/generate-php-base.sh, like reading the release managers' keys from the repo instead of a keyserver. scripts/test-base-image.sh checks it against the official image.
  • No PECL. The default redis extension builds from pinned phpredis commits on GitHub.
  • Releases start from a tag push. CI builds, tests, and publishes the images, then publishes the draft release. If a build fails, the tag isn't locked yet, so you fix it and push the tag again.
  • Safe backports. Floating tags like 8.4-fpm-nginx only move for the newest release. Older versions get release tags only.
  • A release watcher. Every 15 minutes, CI checks php.net. When a new patch is out, it compiles the base images and opens an issue with the tag to push.
  • A weekly upstream check. It diffs our vendored files against docker-library/php and compares our base images with the official ones.

This is meant to ship as v5.1. Users get the same tags, paths, and docker-php-ext-* and install-php-extensions tooling.

How to test

Build an image on PHP compiled from source:

scripts/dev.sh --variation fpm-nginx --version 8.4 --os trixie --php-from-source
scripts/test-image.sh serversideup/php:8.4-fpm-nginx-trixie 8.4.27

The first CI run on this PR compiles all 44 base images into serversideup/php-dev. That run also tells us what this costs on Depot.

Notes for reviewers

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying serversideup-php with  Cloudflare Pages  Cloudflare Pages

Latest commit: df5875b
Status: ✅  Deploy successful!
Preview URL: https://0ec04b5b.serversideup-php.pages.dev
Branch Preview URL: https://build-from-source.serversideup-php.pages.dev

View logs

@github-actions

Copy link
Copy Markdown
Contributor

Images for PR #728

Build Test Publish
✅ 79 of 79 images built ✅ Every image passed on amd64 and arm64 ✅ Published to serversideup/php-dev

Try it:

docker run --rm -v "$PWD:/var/www/html" -p 8080:8080 serversideup/php-dev:728-8.5-fpm-nginx

Every image is on Docker Hub as serversideup/php-dev:728-<php>-<variation>-<os>. Browse all tags or view the run.

All images with sizes

Sizes are compressed, per architecture.

Variation PHP Base OS amd64 arm64 Image
cli 8.5.12 alpine3.23 48.7 MB 48.0 MB serversideup/php-dev:728-8.5.12-cli-alpine3.23
cli 8.5.12 alpine3.24 48.6 MB 48.1 MB serversideup/php-dev:728-8.5.12-cli-alpine3.24
cli 8.5.12 bookworm 198.2 MB 189.7 MB serversideup/php-dev:728-8.5.12-cli-bookworm
cli 8.5.12 trixie 197.5 MB 188.2 MB serversideup/php-dev:728-8.5.12-cli-trixie
cli 8.4.27 alpine3.23 45.4 MB 45.1 MB serversideup/php-dev:728-8.4.27-cli-alpine3.23
cli 8.4.27 alpine3.24 45.5 MB 45.1 MB serversideup/php-dev:728-8.4.27-cli-alpine3.24
cli 8.4.27 bookworm 194.0 MB 185.9 MB serversideup/php-dev:728-8.4.27-cli-bookworm
cli 8.4.27 trixie 193.4 MB 184.4 MB serversideup/php-dev:728-8.4.27-cli-trixie
cli 8.3.36 alpine3.23 41.3 MB 41.3 MB serversideup/php-dev:728-8.3.36-cli-alpine3.23
cli 8.3.36 alpine3.24 41.3 MB 41.4 MB serversideup/php-dev:728-8.3.36-cli-alpine3.24
cli 8.3.36 bookworm 189.1 MB 181.3 MB serversideup/php-dev:728-8.3.36-cli-bookworm
cli 8.3.36 trixie 188.4 MB 179.8 MB serversideup/php-dev:728-8.3.36-cli-trixie
cli 8.2.35 alpine3.23 40.4 MB 40.5 MB serversideup/php-dev:728-8.2.35-cli-alpine3.23
cli 8.2.35 alpine3.24 40.5 MB 40.6 MB serversideup/php-dev:728-8.2.35-cli-alpine3.24
cli 8.2.35 bookworm 188.1 MB 180.4 MB serversideup/php-dev:728-8.2.35-cli-bookworm
cli 8.2.35 trixie 187.5 MB 178.9 MB serversideup/php-dev:728-8.2.35-cli-trixie
cli 8.1.34 alpine3.22 42.4 MB 43.0 MB serversideup/php-dev:728-8.1.34-cli-alpine3.22
cli 8.1.34 bookworm 185.4 MB 178.7 MB serversideup/php-dev:728-8.1.34-cli-bookworm
cli 8.1.34 trixie 185.2 MB 178.1 MB serversideup/php-dev:728-8.1.34-cli-trixie
fpm 8.5.12 alpine3.23 42.5 MB 42.1 MB serversideup/php-dev:728-8.5.12-fpm-alpine3.23
fpm 8.5.12 alpine3.24 42.6 MB 42.3 MB serversideup/php-dev:728-8.5.12-fpm-alpine3.24
fpm 8.5.12 bookworm 185.9 MB 177.9 MB serversideup/php-dev:728-8.5.12-fpm-bookworm
fpm 8.5.12 trixie 185.3 MB 176.5 MB serversideup/php-dev:728-8.5.12-fpm-trixie
fpm 8.4.27 alpine3.23 40.2 MB 40.0 MB serversideup/php-dev:728-8.4.27-fpm-alpine3.23
fpm 8.4.27 alpine3.24 40.3 MB 40.1 MB serversideup/php-dev:728-8.4.27-fpm-alpine3.24
fpm 8.4.27 bookworm 183.7 MB 175.8 MB serversideup/php-dev:728-8.4.27-fpm-bookworm
fpm 8.4.27 trixie 183.0 MB 174.4 MB serversideup/php-dev:728-8.4.27-fpm-trixie
fpm 8.3.36 alpine3.23 37.0 MB 37.2 MB serversideup/php-dev:728-8.3.36-fpm-alpine3.23
fpm 8.3.36 alpine3.24 37.0 MB 37.2 MB serversideup/php-dev:728-8.3.36-fpm-alpine3.24
fpm 8.3.36 bookworm 180.5 MB 173.0 MB serversideup/php-dev:728-8.3.36-fpm-bookworm
fpm 8.3.36 trixie 179.8 MB 171.5 MB serversideup/php-dev:728-8.3.36-fpm-trixie
fpm 8.2.35 alpine3.23 36.3 MB 36.5 MB serversideup/php-dev:728-8.2.35-fpm-alpine3.23
fpm 8.2.35 alpine3.24 36.3 MB 36.5 MB serversideup/php-dev:728-8.2.35-fpm-alpine3.24
fpm 8.2.35 bookworm 179.8 MB 172.3 MB serversideup/php-dev:728-8.2.35-fpm-bookworm
fpm 8.2.35 trixie 179.1 MB 170.8 MB serversideup/php-dev:728-8.2.35-fpm-trixie
fpm 8.1.34 alpine3.22 38.5 MB 39.2 MB serversideup/php-dev:728-8.1.34-fpm-alpine3.22
fpm 8.1.34 bookworm 177.6 MB 171.1 MB serversideup/php-dev:728-8.1.34-fpm-bookworm
fpm 8.1.34 trixie 177.4 MB 170.4 MB serversideup/php-dev:728-8.1.34-fpm-trixie
fpm-apache 8.5.12 bookworm 192.2 MB 184.8 MB serversideup/php-dev:728-8.5.12-fpm-apache-bookworm
fpm-apache 8.5.12 trixie 191.7 MB 183.4 MB serversideup/php-dev:728-8.5.12-fpm-apache-trixie
fpm-apache 8.4.27 bookworm 190.1 MB 182.6 MB serversideup/php-dev:728-8.4.27-fpm-apache-bookworm
fpm-apache 8.4.27 trixie 189.4 MB 181.2 MB serversideup/php-dev:728-8.4.27-fpm-apache-trixie
fpm-apache 8.3.36 bookworm 186.8 MB 179.8 MB serversideup/php-dev:728-8.3.36-fpm-apache-bookworm
fpm-apache 8.3.36 trixie 186.2 MB 178.4 MB serversideup/php-dev:728-8.3.36-fpm-apache-trixie
fpm-apache 8.2.35 bookworm 186.1 MB 179.1 MB serversideup/php-dev:728-8.2.35-fpm-apache-bookworm
fpm-apache 8.2.35 trixie 185.5 MB 177.7 MB serversideup/php-dev:728-8.2.35-fpm-apache-trixie
fpm-apache 8.1.34 bookworm 183.9 MB 177.9 MB serversideup/php-dev:728-8.1.34-fpm-apache-bookworm
fpm-apache 8.1.34 trixie 183.8 MB 177.3 MB serversideup/php-dev:728-8.1.34-fpm-apache-trixie
fpm-nginx 8.5.12 alpine3.23 48.5 MB 48.7 MB serversideup/php-dev:728-8.5.12-fpm-nginx-alpine3.23
fpm-nginx 8.5.12 alpine3.24 50.0 MB 50.2 MB serversideup/php-dev:728-8.5.12-fpm-nginx-alpine3.24
fpm-nginx 8.5.12 bookworm 193.7 MB 186.1 MB serversideup/php-dev:728-8.5.12-fpm-nginx-bookworm
fpm-nginx 8.5.12 trixie 200.1 MB 191.4 MB serversideup/php-dev:728-8.5.12-fpm-nginx-trixie
fpm-nginx 8.4.27 alpine3.23 46.3 MB 46.6 MB serversideup/php-dev:728-8.4.27-fpm-nginx-alpine3.23
fpm-nginx 8.4.27 alpine3.24 47.7 MB 48.0 MB serversideup/php-dev:728-8.4.27-fpm-nginx-alpine3.24
fpm-nginx 8.4.27 bookworm 191.5 MB 184.0 MB serversideup/php-dev:728-8.4.27-fpm-nginx-bookworm
fpm-nginx 8.4.27 trixie 197.8 MB 189.3 MB serversideup/php-dev:728-8.4.27-fpm-nginx-trixie
fpm-nginx 8.3.36 alpine3.23 43.1 MB 43.7 MB serversideup/php-dev:728-8.3.36-fpm-nginx-alpine3.23
fpm-nginx 8.3.36 alpine3.24 44.5 MB 45.1 MB serversideup/php-dev:728-8.3.36-fpm-nginx-alpine3.24
fpm-nginx 8.3.36 bookworm 188.2 MB 181.2 MB serversideup/php-dev:728-8.3.36-fpm-nginx-bookworm
fpm-nginx 8.3.36 trixie 194.6 MB 186.5 MB serversideup/php-dev:728-8.3.36-fpm-nginx-trixie
fpm-nginx 8.2.35 alpine3.23 42.4 MB 43.0 MB serversideup/php-dev:728-8.2.35-fpm-nginx-alpine3.23
fpm-nginx 8.2.35 alpine3.24 43.8 MB 44.4 MB serversideup/php-dev:728-8.2.35-fpm-nginx-alpine3.24
fpm-nginx 8.2.35 bookworm 187.6 MB 180.5 MB serversideup/php-dev:728-8.2.35-fpm-nginx-bookworm
fpm-nginx 8.2.35 trixie 193.9 MB 185.8 MB serversideup/php-dev:728-8.2.35-fpm-nginx-trixie
fpm-nginx 8.1.34 alpine3.22 44.6 MB 45.8 MB serversideup/php-dev:728-8.1.34-fpm-nginx-alpine3.22
fpm-nginx 8.1.34 bookworm 186.5 MB 180.3 MB serversideup/php-dev:728-8.1.34-fpm-nginx-bookworm
fpm-nginx 8.1.34 trixie 194.0 MB 187.2 MB serversideup/php-dev:728-8.1.34-fpm-nginx-trixie
frankenphp 8.5.12 alpine3.23 77.8 MB 74.8 MB serversideup/php-dev:728-8.5.12-frankenphp-alpine3.23
frankenphp 8.5.12 alpine3.24 77.8 MB 74.9 MB serversideup/php-dev:728-8.5.12-frankenphp-alpine3.24
frankenphp 8.5.12 bookworm 220.0 MB 209.7 MB serversideup/php-dev:728-8.5.12-frankenphp-bookworm
frankenphp 8.5.12 trixie 219.4 MB 208.1 MB serversideup/php-dev:728-8.5.12-frankenphp-trixie
frankenphp 8.4.27 alpine3.23 73.5 MB 70.9 MB serversideup/php-dev:728-8.4.27-frankenphp-alpine3.23
frankenphp 8.4.27 alpine3.24 73.6 MB 71.1 MB serversideup/php-dev:728-8.4.27-frankenphp-alpine3.24
frankenphp 8.4.27 bookworm 215.9 MB 205.8 MB serversideup/php-dev:728-8.4.27-frankenphp-bookworm
frankenphp 8.4.27 trixie 215.2 MB 204.3 MB serversideup/php-dev:728-8.4.27-frankenphp-trixie
frankenphp 8.3.36 alpine3.23 68.6 MB 66.4 MB serversideup/php-dev:728-8.3.36-frankenphp-alpine3.23
frankenphp 8.3.36 alpine3.24 68.6 MB 66.5 MB serversideup/php-dev:728-8.3.36-frankenphp-alpine3.24
frankenphp 8.3.36 bookworm 210.9 MB 201.2 MB serversideup/php-dev:728-8.3.36-frankenphp-bookworm
frankenphp 8.3.36 trixie 210.2 MB 199.7 MB serversideup/php-dev:728-8.3.36-frankenphp-trixie

Updated on every push to this PR.

@mbrodala

Copy link
Copy Markdown
Contributor

If a build fails, the tag isn't locked yet, so you fix it and push the tag again.

Even if not right now this is something keep in mind and review later. Tags pushed to Github should also be fixed forever. Otherwise an attacker which succeeded taking over an account can recreate existing tags with malicious changes.

@jaydrogers

Copy link
Copy Markdown
Member Author

Even if not right now this is something keep in mind and review later. Tags pushed to Github should also be fixed forever. Otherwise an attacker which succeeded taking over an account can recreate existing tags with malicious changes.

Already set with immutable tags. Security begins without even trusting yourself 😅

@mbrodala

Copy link
Copy Markdown
Contributor

Even if not right now this is something keep in mind and review later. Tags pushed to Github should also be fixed forever. Otherwise an attacker which succeeded taking over an account can recreate existing tags with malicious changes.

Already set with immutable tags. Security begins without even trusting yourself 😅

Hm, can you elaborate on that? I was exactly referring to immutable tags but the quoted text indicates that tags can be removed and pushed again, pointing at a different change than the original broken tag.

You see me confused. ;-)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants