PHP Academy · leksjon

Bygg med flere trinn og optimalisering

Gjør imagene mindre, og skill bygging fra kjøring.

Leksjon 2 av 413 trinn

Bygg med flere trinn og optimalisering er en gratis leksjon i PHP Academy på CoddyKit. Dette er leksjon 2 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i PHP Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i PHP Academy inneholder totalt 4 leksjoner.

Hvorfor flerstegsbygging

Et image med ett trinn tar med Composer, byggeavhengigheter, utviklingsheadere og mappen tests/ inn i produksjon. Flerstegsbygg gjør at du kan kompilere og installere i et omfattende builder-steg og bare kopiere de ferdige artefaktene til et slankt runtime-steg.

Resultatet er mindre images, en mindre angrepsflate, raskere nedlastinger og ingen kompilatorer i produksjonsmiljøet.

Navngitte steg

Hver FROM ... AS name starter et nytt steg. Senere steg kan bruke COPY --from=name til å kopiere filer fra tidligere steg. Bare det siste steget blir imaget ditt; mellomliggende steg forkastes, men legges i cache.

# Stage 1: dependencies
FROM composer:2 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --prefer-dist --ignore-platform-reqs

# Stage 2: runtime
FROM php:8.3-fpm-alpine AS runtime
WORKDIR /app
COPY --from=vendor /app/vendor ./vendor
COPY . .

Skille ut byggeavhengigheter

Kompilering av utvidelser krever autoconf, gcc og utviklingsheadere – ingen av disse hører hjemme i kjøretidsmiljøet. Bruk installasjonsprogrammet i et builder-steg, og kopier deretter de kompilerte .so-filene og den tilhørende conf.d-ini-filen til et rent runtime-steg.

FROM php:8.3-fpm-alpine AS ext-builder
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions && \
    install-php-extensions redis igbinary opcache intl

FROM php:8.3-fpm-alpine AS runtime
# Copy compiled extensions + their enable configs
COPY --from=ext-builder /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
COPY --from=ext-builder /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/

Rekkefølge for lagring i cache

Docker legger lag i cache ovenfra og ned og ugyldiggjør alt under et lag som er endret. Ordne dem fra minst til oftest endret:

  • Base + utvidelser (sjelden)
  • composer.lock + installasjon (av og til)
  • Applikasjonskildekode (hver commit)
  • Autoload-dump (hver commit)

Det betyr at en endring som bare gjelder kode, kan gjenbruke hele laget med vendor-filer fra cachen.

# BAD: copying all source before composer install
# busts the vendor layer on every code change
COPY . .
RUN composer install

# GOOD: lock first, then source
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-autoloader
COPY . .
RUN composer dump-autoload --optimize

BuildKit-cachemonteringer

Med BuildKit (DOCKER_BUILDKIT=1) kan du montere en vedvarende cache som overlever mellom bygg uten å havne i imaget. Det er perfekt for Composer sin globale cache, slik at gjentatte bygg slipper å laste ned pakker på nytt.

# syntax=docker/dockerfile:1
FROM composer:2 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN --mount=type=cache,target=/tmp/composer-cache \
    COMPOSER_CACHE_DIR=/tmp/composer-cache \
    composer install --no-dev --prefer-dist

Måle imagestørrelsen

Undersøk lagfordelingen for å finne overflødig innhold. docker history viser hvor mye hver instruksjon la til; verktøy som dive viser bortkastet plass. Målet er et runtime-steg uten kompilatorer, Composer eller utviklingsavhengigheter.

# Compare sizes
docker images myapp

# Per-layer contribution
docker history --no-trunc --format '{{.Size}}\t{{.CreatedBy}}' myapp:latest

# Deep inspection of wasted bytes
dive myapp:latest

Strømlinjeforme det siste steget

Runtime-steget skal IKKE inneholde Composer, skriptet for installasjon av utvidelser eller testpakken din. Kopier vendor og kildekoden fra builder-stegene; kjør aldri composer i det siste steget. Fjern installasjonsprogrammet etter bruk hvis du må kjøre det der.

FROM php:8.3-fpm-alpine AS runtime
WORKDIR /app

# bring extensions + vendor in from builders — no Composer here
COPY --from=ext-builder /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
COPY --from=ext-builder /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/
COPY --from=vendor /app/vendor ./vendor
COPY . .

USER www-data
CMD ["php-fpm"]

Begrensninger ved distroless / scratch

PHP kan ikke kjøre på en helt tom scratch – det trenger libc og delte biblioteker. Det praktiske minimumet er alpine (musl) eller en minimal Debian i distroless-stil. Alpine er minst, men vær oppmerksom på native biblioteker som forventer glibc. Hvis du får segmenteringsfeil med NSS/ICU, går du tilbake til php:8.3-fpm-bookworm.

# Smallest practical PHP runtime
FROM php:8.3-fpm-alpine

# If musl causes native-lib issues (e.g., some ICU edge cases),
# the glibc Debian slim variant is the safe fallback:
# FROM php:8.3-fpm-bookworm

Målrette steg

Én Dockerfile kan brukes til både utvikling og produksjon ved hjelp av --target. Legg til et dev-steg oppå runtime-steget som legger til Composer-utviklingsavhengigheter og Xdebug igjen. Bygg --target=runtime for produksjon og --target=dev lokalt.

FROM runtime AS dev
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions && \
    install-php-extensions xdebug @composer
USER root
RUN composer install   # includes dev deps

# Build prod:  docker build --target runtime -t app:prod .
# Build dev:   docker build --target dev     -t app:dev  .

Forstå lagstørrelser

En enkel mental modell hjelper deg med å forutsi cacheatferden. Dette CLI-utdraget simulerer den klassiske feilen med ubegrenset lagvekst sammenlignet med en avgrenset variant, og viser hvorfor det er viktig å kombinere oppryddingen med den samme RUN-instruksjonen.

<?php
// Simulate layer sizes (MB) for two strategies
$installSteps = [120, 8, 8, 8];

// Separate RUN per step keeps temp files in layers
$separate = array_sum($installSteps);

// Single RUN with cleanup removes temp files before commit
$combined = max($installSteps); // peak, then cleaned

echo "Separate layers total: {$separate} MB\n";
echo "Combined+cleanup:       {$combined} MB\n";
echo 'Saved: ' . ($separate - $combined) . " MB\n";
?>

Kombiner installasjon og opprydding i én RUN

Hver RUN er et lag. Hvis du sletter filer i et senere lag, blir imaget ikke mindre, fordi de tidligere lagene fortsatt inneholder bytene. Installer, bruk og rydd opp i én enkelt RUN, slik at midlertidige filer aldri blir lagret i et lag.

RUN apk add --no-cache --virtual .build-deps $PHPIZE_DEPS && \
    pecl install redis && \
    docker-php-ext-enable redis && \
    apk del .build-deps && \
    rm -rf /tmp/pear /var/cache/apk/*

Hurtigsjekk

Hvorfor må byggeavhengigheter fjernes i samme RUN som installerte dem?

Oppsummering

Flerstegsbygg holder kompilatorer og utviklingsavhengigheter ute av produksjonen. Du har lært å navngi steg og bruke COPY --from for artefakter, ordne lag fra minst til mest omskiftelige for caching, bruke BuildKit-cachemonteringer for Composer, måle størrelse med docker history/dive, velge alpine eller glibc med hensikt, målrette utviklings- og produksjonssteg og kombinere installasjon og opprydding i én RUN.

Gratis å komme i gang

Lær deg PHP med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
49
Leksjoner
195

Ofte stilte spørsmål

Er leksjonen «Bygg med flere trinn og optimalisering» gratis?

Ja – hele teksten i «Bygg med flere trinn og optimalisering» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av PHP Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i PHP Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Bygg med flere trinn og optimalisering»?

Gjør imagene mindre, og skill bygging fra kjøring. Du øver på PHP Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med PHP Academy?

Ingen tidligere erfaring er nødvendig. PHP Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.

Hvor lang tid tar leksjonen «Bygg med flere trinn og optimalisering»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne PHP Academy-leksjonen?

Ja. Alle PHP Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Konte||||trenger en PHP-applikasjon
  2. Bygg med flere trinn og optimalisering
  3. Docker Compose for lokale stacker
  4. CI/CD med GitHub Actions
← Tilbake til PHP Academy