Skip to content

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

@akirayamamoto

Description

@akirayamamoto

Description

Dockerfile.alpine uses FROM php:8-alpine and then runs apk add php-apache2 … to install Apache + mod_php. The result is two PHP installs side by side in the same image:

  • The docker-library PHP at /usr/local/bin/php (~30 MB) reading /usr/local/etc/php/conf.d. Never used: Apache loads mod_php from the apk packages, not this binary.
  • The apk-installed PHP at /usr/bin/php reading /etc/phpXX/conf.d. This is the one mod_php uses.

Beyond the unused binary, the FROM image also carries PHP source headers under /usr/src/php and build artifacts that aren't needed at runtime. A fresh build of current master lands at ~227 MB.

Switching the base to plain alpine:3.23 and installing PHP via apk only drops the image to ~102 MB, a 56% reduction. Apache still serves the same speedtest with the same mod_php.

Background

#201 (2019) originally proposed FROM alpine:latest, and the maintainer at the time said yes. That work stalled. #631 (2024) eventually shipped Dockerfile.alpine from a different contributor using FROM php:8-alpine. The review focused on Docker labels and PHP version (8.2 → 8.3); the FROM choice wasn't questioned. The dual-install layout has been carrying ~120 MB of dead weight since the file landed.

Proposed change

Replace FROM php:8-alpine with FROM alpine:3.23 (current latest stable) and add php to the apk package list so /usr/bin/php is guaranteed.

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

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

Verification

Built both variants on the same host:

libsp-old:alpine  227 MB  (master HEAD, FROM php:8-alpine)
libsp-exp:alpine  102 MB  (FROM alpine:3.23)

Inside the experiment image: only /usr/bin/php exists, command -v php returns the apk binary, and mod_php is /usr/lib/apache2/mod_php84.so from the php84-apache2 package — same PHP major as master's FROM php:8-alpine.

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

Notes

  • alpine:3.23's php-apache2 meta resolves to php84-apache2, the same PHP major the current master image lands on via FROM php:8-alpine. No version regression.
  • Base-image swap only, no application code change.
  • Dependabot needs no config change: the docker ecosystem at / auto-discovers FROM lines, so it'll drop php:8-alpine and pick up alpine:3.23 automatically. One behavior shift to be aware of: future Alpine bumps via Dependabot can carry implicit PHP major bumps when the apk meta shifts (e.g., 3.24 might move php-apache2 to php85). If you want PHP locked to a major, pin php84-apache2 and the matching extension packages explicitly.

PR open: #800.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions