Produkcyjna alternatywa dla docker-library/php, zbudowana na Gentoo Hardened, dostarczana jako FROM scratch, zawsze nonroot.
- Bezpieczeństwo
- Minimalny rozmiar
- Wydajność
- Zgodność z docker-library/php
- Rozszerzalność
export PHP_GPG_KEYS="<fingerprinty z https://www.php.net/downloads.php>"
# Domyślnie linux/amd64 (nawet na Mac Apple Silicon)
make cli
# Inna architektura
make cli ARCH=arm64
make all ARCH=arm64
# Bezpośrednio przez Docker
docker build --platform linux/amd64 -f docker/Dockerfile --target cli ...
docker build --platform linux/arm64 -f docker/Dockerfile --target cli ...ARCH |
Platforma | Tag (multi-arch w registry) |
|---|---|---|
amd64 (domyślnie) |
linux/amd64 |
ghcr.io/lemric/gentoo-php/php:cli-8.5.8 |
arm64 |
linux/arm64 |
ten sam tag — manifest wybiera architekturę |
make all # zalecane: bake cli + fpm (ARCH=amd64 domyślnie)
make verify
docker buildx bake -f docker-bake.hcl all # amd64
docker buildx bake -f docker-bake.hcl all --set ARCH=arm64
# CI: bake per arch → manifest job łączy w cli-8.5.8 / fpm-8.5.8builder-base → toolchain → php-builder → builder-php
→ collect-cli / collect-fpm → scratch-runtime → cli / fpm
Szczegóły: docs/ARCHITECTURE.md
| Target | Tag | Opis |
|---|---|---|
cli |
php:cli-8.5.8 |
Produkcja — minimalny scratch runtime, UID 82 |
fpm |
php:fpm-8.5.8 |
Produkcja — minimalny FPM scratch, UID 82 |
cli-build |
php:cli-build-8.5.8 |
Multi-stage helper — PIE, phpize, install-lib (nie deployuj) |
fpm-build |
php:fpm-build-8.5.8 |
Multi-stage helper dla FPM |
Interfejs identyczny:
docker-php-sourcedocker-php-ext-configuredocker-php-ext-installdocker-php-ext-enabledocker-php-pie-install(alias:docker-php-pecl-install)docker-php-envinstall-lib(Gentoo atoms via bundled Portage; wymagaUSER rootw RUN)docker-php-install-cleanup(automatycznie po każdej instalacji)docker-php-export-runtime(eksport overlay do multi-stage)docker-php-entrypoint(identyczny skrypt jak w docker-library/php)
Bazowy zestaw rozszerzeń = core only (jak php:8.5-cli / php:8.5-fpm).
Nie ma gd, intl, zip, pdo_mysql — dokładasz w multi-stage (cli-build / fpm-build) lub w builder-php.
Runtime ini — zgodność z docker-library. OPcache wyłączony w base (jak official); opcjonalnie configs/php/conf.d/opcache-production.ini.
Redis, xdebug itd. — multi-stage z docker-php-pie-install.
Base FPM = OPcache off (jak php:8.5-fpm). W obrazie aplikacji:
COPY configs/php/conf.d/opcache-production.ini /usr/local/etc/php/conf.d/
# po deploy: kill -USR2 $(cat /tmp/php-fpm.pid) # reload workersExtra lockdown (wyłącza Composer/queue): configs/php/conf.d/hardening-strict.ini.
Odkomentuj sekcję w stage builder-php:
RUN install-lib libjpeg libpng freetype \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j"$(nproc)" gdcli / fpm = minimalny runtime (bez gcc, emerge, phpize).
cli-build / fpm-build = helper do instalacji rozszerzeń — używaj tylko jako stage pośredni.
FROM ghcr.io/lemric/gentoo-php/php:cli-build-8.5.8 AS ext
RUN install-lib libjpeg libpng freetype \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd \
&& docker-php-pie-install redis \
&& docker-php-export-runtime /export
FROM ghcr.io/lemric/gentoo-php/php:cli-8.5.8
COPY --from=ext /export/ /
USER www-dataFinalny obraz = tylko runtime + rozszerzenia (ldd closure). Install stack nie trafia do produkcji.
Rozszerzenia spoza core PHP: PIE (docker-php-pie-install).
Skróty PECL (redis, xdebug) mapują się przez scripts/build/pie-package-map.
docker-php-pecl-install to symlink — stary interfejs działa.
Przykład: examples/Dockerfile.gd
| Rozszerzenie | install-lib |
|---|---|
| gd | libjpeg libpng freetype |
| intl | icu |
| zip | libzip |
| pdo_pgsql | libpq |
| gmp | gmp |
Pełna mapa: scripts/build/install-lib
php+ ldd closure,/bin/sh(busybox) +/bin/bash(Gentoo)/usr/bin/env,/usr/bin/wget,/usr/bin/php— busybox / symlinkdocker-php-entrypoint— jak w docker-library (-f→ php)- Composer, artisan, queue —
proc_open,putenv,pcntl,symlinkdostępne - Brak gcc, emerge, phpize, PIE w runtime
php-fpm+ ldd closure —/bin/sh+/bin/bashENTRYPOINT docker-php-entrypoint+CMD php-fpmhardening-production.ini— prod defaults (docker-library parity)- FPM:
security.limit_extensions = .php, ping/fpm-ping - OPcache off w base; opcjonalnie skopiuj
configs/php/conf.d/opcache-production.ini
- Wszystko z runtime + PIE, phpize,
install-lib, Portage binpkg w/usr/local/libexec/install - Po instalacji:
docker-php-export-runtime /export→ skopiuj do minimalnegocli/fpm
Każdy skrypt instalacji kończy się obowiązkowym cleanup (temp, cache, strip .so).
- Gentoo hardened profile (PIE, SSP, CET)
- FULL RELRO (
-Wl,-z,now) - FORTIFY_SOURCE=3
- Produkcja CLI i FPM:
/bin/sh(busybox) +/bin/bash(Gentoo + ldd closure) - fail-closed
harden-runtime.sh+verify-hardening.sh - Zawsze USER 82:82 (www-data)
- FPM: SIGQUIT,
security.limit_extensions - HEALTHCHECK — PHP probes (bez sh)
- CI: multi-arch manifests, BuildKit cache
Wbudowany /usr/local/libexec/php/docker-php-healthcheck.php (PHP, bez shell):
| Probe | FPM | CLI |
|---|---|---|
startup |
php-fpm -t (K8s) / sanity config |
PHP ≥ 8.0 |
liveness |
PID file lub port :9000 |
always OK |
readiness |
FastCGI ping (/fpm-ping → pong) |
core extensions |
health |
liveness + readiness | readiness |
# Shebang #!/usr/bin/env php (Symfony, Composer bin, itp.)
docker run --rm -v "$PWD:/app" -w /app \
ghcr.io/lemric/gentoo-php/php:cli-8.5.8 ./bin/console
# Shell interaktywny / skrypt bash
docker run --rm -it ghcr.io/lemric/gentoo-php/php:cli-8.5.8 /bin/bash
docker run --rm ghcr.io/lemric/gentoo-php/php:cli-8.5.8 /bin/bash deploy.sh
docker run --rm -it ghcr.io/lemric/gentoo-php/php:fpm-8.5.8 /bin/bash
# Healthcheck (exec, bez shella)
docker run --rm --entrypoint php ghcr.io/lemric/gentoo-php/php:cli-8.5.8 \
/usr/local/libexec/php/docker-php-healthcheck.php healthFPM pool ma ping.path = /fpm-ping i ping.response = pong (konfigurowalne przez env).
Przykład Kubernetes: examples/k8s/fpm-probes.yaml
securityContext:
runAsNonRoot: true
runAsUser: 82
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
seccompProfile:
type: RuntimeDefault
capabilities:
drop: ["ALL"]
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}| Official | Gentoo Scratch | |
|---|---|---|
| Baza | Debian | scratch |
| FPM root | tak (setuid) | nie (zawsze www-data) |
| Shell | /bin/sh (dash) + /bin/bash |
busybox /bin/sh + Gentoo /bin/bash |
| Entrypoint | docker-php-entrypoint |
cli + fpm: docker-php-entrypoint |
| OPcache (base FPM) | off | off (opcjonalny opcache-production.ini) |
| Optymalizacja | -O2 |
-O3 + ThinLTO + -march |
docker/Dockerfile # Pipeline (wszystkie stage)
docker-bake.hcl # Multi-arch CI
portage/ # make.conf, USE, package.env
scripts/ # docker-php-*, collect-runtime, install-lib
configs/ # FPM, opcache
docs/ARCHITECTURE.md # Decyzje architektoniczne
Makefile # Lokalne targety
- Zmień
PHP_VERSIONwMakefile/docker-bake.hcl - Pobierz nowe
PHP_GPG_KEYSz php.net - Opcjonalnie ustaw
PHP_SHA256 make verify
PHP sources: PHP License v3.01. Build scripts: MIT.