Skip to content

Drop FROM php:8-alpine in favor of FROM alpine:3.23 (~55% smaller image)#800

Open
akirayamamoto wants to merge 2 commits intolibrespeed:masterfrom
akirayamamoto:experiment/alpine-base-no-php
Open

Drop FROM php:8-alpine in favor of FROM alpine:3.23 (~55% smaller image)#800
akirayamamoto wants to merge 2 commits intolibrespeed:masterfrom
akirayamamoto:experiment/alpine-base-no-php

Conversation

@akirayamamoto
Copy link
Copy Markdown

Fixes #799.

Replace FROM php:8-alpine with FROM alpine:3.23 in Dockerfile.alpine and install PHP entirely via apk. See #799 for the full context. Short version: the FROM image's /usr/local/bin/php is never used by Apache (mod_php loads from the apk packages instead), and the FROM image also carries PHP source/build artifacts the runtime doesn't need.

Change

-FROM php:8-alpine
+FROM alpine:3.23
 RUN apk add --quiet --no-cache \
     bash \
     apache2 \
+    php \
     php-apache2 \
     php-ctype \
     ...

The dead docker-php-extension-installer comment block also goes; it never applied to the alpine variant.

Image size

libsp-old:alpine  227 MB  (master HEAD)
libsp-exp:alpine  102 MB  (this PR)

The savings come from dropping the unused /usr/local/bin/php binary plus the /usr/src/php headers and build artifacts that the docker-library php:8-alpine image carries. ~55% smaller.

Verification

Inside the new image:

$ ls /usr/local/bin/php /usr/bin/php* 2>/dev/null
lrwxrwxrwx ... /usr/bin/php -> php84
-rwxr-xr-x ... /usr/bin/php84
$ command -v php
/usr/bin/php
$ ls /usr/lib/apache2/mod_php*.so
/usr/lib/apache2/mod_php84.so

One PHP install, no FROM-image leftovers, and mod_php is still served by the same php-apache2 package — which on alpine:3.23 resolves to php84, same major as master's FROM php:8-alpine.

Full Playwright e2e suite passes against this image: 12/12, 22.4s. Specs: classic-standalone-regression, design-switch, modes, title-special-chars across standalone/backend/frontend/dual configs.

Note on PHP version

alpine:3.23's php-apache2 meta resolves to php84-apache2, matching the PHP major that master's FROM php:8-alpine lands on today. No version regression and no need to pin a versioned package. Earlier alpine releases (3.21, 3.22) defaulted to php83; if a future Alpine bump shifts the default again, pinning php84-* explicitly is the escape hatch.

Dependabot

.github/dependabot.yml's docker ecosystem at / auto-discovers FROM lines. After this PR, Dependabot drops php:8-alpine and picks up alpine:3.23. No config change needed. One subtle shift: Alpine bumps now carry the implicit risk of a PHP major bump when the apk meta shifts — see the PHP-version note above for the lock-down option.

The current Dockerfile.alpine pulls FROM php:8-alpine and then `apk
add php-apache2`. The result is two PHP installs side by side: the
docker-library PHP at /usr/local/bin/php (~30 MB, never used by
Apache) and the apk-installed PHP at /usr/bin/php (which mod_php
actually loads).

Pinning a fresh Alpine release and installing the apk packages
directly drops the dead /usr/local/bin/php install entirely.
Expected wins:
- Smaller image (~30 MB less; 2024 baseline was ~120 MB)
- One PHP binary, no $PATH ambiguity
- Cleaner story for any follow-up that touches PHP config
@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Replace php:8-alpine with alpine:3.23 for smaller image

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Replace FROM php:8-alpine with FROM alpine:3.23 base image
• Install PHP via apk packages instead of inheriting unused binary
• Remove dead docker-php-extension-installer comment block
• Reduce image size by ~55% (227 MB to 102 MB)
Diagram
flowchart LR
  A["FROM php:8-alpine<br/>227 MB"] -->|Remove unused binary<br/>and build artifacts| B["FROM alpine:3.23<br/>102 MB"]
  B -->|Add php package| C["Single PHP install<br/>via apk"]
  C -->|mod_php loads from| D["php-apache2 package<br/>php84"]
Loading

Grey Divider

File Changes

1. Dockerfile.alpine ✨ Enhancement +2/-7

Replace PHP base image with Alpine base

• Changed base image from php:8-alpine to alpine:3.23
• Added explicit php package to apk installation list
• Removed commented-out docker-php-extension-installer block (lines 13-17)
• Kept all other PHP extension packages unchanged

Dockerfile.alpine


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

qodo-free-for-open-source-projects Bot commented Apr 27, 2026

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Missing CA certificates🐞 Bug ☼ Reliability
Description
Dockerfile.alpine installs PHP/Apache but not a CA bundle, so PHP HTTPS requests (e.g.,
backend/getIP.php calling ipinfo.io when IPINFO_APIKEY is configured) can fail TLS verification at
runtime and break ISP detection.
Code

Dockerfile.alpine[R1-8]

+FROM alpine:3.23
RUN apk add --quiet --no-cache \
   bash \
   apache2 \
+    php \
   php-apache2 \
   php-ctype \
   php-phar \
Evidence
The Alpine Dockerfile’s apk install list does not include ca-certificates, yet the application
performs HTTPS requests to ipinfo.io when IPINFO_APIKEY is provided via the container
environment/entrypoint. Without a CA trust store in the image, those HTTPS requests may fail during
TLS verification.

Dockerfile.alpine[1-17]
backend/getIP.php[53-66]
docker/entrypoint.sh[55-67]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`Dockerfile.alpine` is now based on `alpine:3.23` and installs PHP via `apk`, but it does not install `ca-certificates`. The app makes outbound HTTPS calls (ipinfo.io) when `IPINFO_APIKEY` is configured; without a CA bundle, these calls can fail due to TLS verification.
### Issue Context
- `backend/getIP.php` calls `file_get_contents('https://ipinfo.io/...')`.
- `docker/entrypoint.sh` wires the `IPINFO_APIKEY` env var into the backend config.
### Fix Focus Areas
- Dockerfile.alpine[1-17]
### Suggested fix
- Add `ca-certificates` to the `apk add --no-cache` list (and optionally run `update-ca-certificates` if you want to be explicit).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread Dockerfile.alpine
ca-certificates-bundle (which provides /etc/ssl/certs/ca-certificates.crt)
is already pulled in transitively by apache2 / php-apache2 on alpine:3.23,
so live HTTPS calls from PHP work today (verified with file_get_contents
against ipinfo.io). But the master image (FROM php:8-alpine) installs
the full ca-certificates package explicitly, and operators with
IPINFO_APIKEY configured rely on outbound HTTPS. Make the dependency
explicit to:

* Match master's package set rather than relying on a transitive pull
  that some future apk dep change could drop.
* Document the runtime TLS requirement at the Dockerfile level instead
  of leaving it implicit.

~50 KB image-size cost; the umbrella ca-certificates package adds the
update-ca-certificates CLI on top of the bundle. Per Qodo's review on
PR librespeed#800.
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.

Dockerfile.alpine carries an unused 30 MB PHP install from FROM php:8-alpine

1 participant