0Pricing
PHP Academy · บทเรียน

การสร้างหลายขั้นตอนและการปรับประสิทธิภาพ

ลดขนาดอิมเมจและแยกขั้นตอนสร้างออกจากการทำงาน

การสร้างหลายขั้นตอนและการปรับประสิทธิภาพ เป็นบทเรียน PHP Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน PHP Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุผลที่ต้องใช้หลายขั้นตอน

อิมเมจแบบขั้นตอนเดียวจะนำ Composer, การอ้างอิงแพ็กเกจสำหรับการสร้าง, ส่วนหัวสำหรับการพัฒนา และโฟลเดอร์ tests/ ติดเข้าไปในสภาพแวดล้อมจริงด้วย การสร้างแบบหลายขั้นตอนช่วยให้คุณคอมไพล์หรือติดตั้งในขั้นตอน สำหรับสร้าง ที่มีเครื่องมือครบ แล้วคัดลอกเฉพาะผลลัพธ์ที่สร้างเสร็จแล้วไปยังขั้นตอน สำหรับทำงาน ที่มีขนาดเล็ก

ผลลัพธ์คือ อิมเมจมีขนาดเล็กลง พื้นที่โจมตีลดลง ดาวน์โหลดได้เร็วขึ้น และไม่มีคอมไพเลอร์ถูกส่งไปยังสภาพแวดล้อมจริง

ขั้นตอนที่มีชื่อ

แต่ละ FROM ... AS name จะเริ่มขั้นตอนใหม่ ขั้นตอนถัดไปสามารถใช้ COPY --from=name เพื่อคัดลอกไฟล์ออกจากขั้นตอนก่อนหน้าได้ เฉพาะขั้นตอน สุดท้าย เท่านั้นที่จะกลายเป็นอิมเมจของคุณ ส่วนขั้นตอนกลางจะถูกทิ้งไป แต่ยังคงถูกแคชไว้

# 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 . .

แยกการอ้างอิงแพ็กเกจสำหรับการสร้าง

การคอมไพล์ส่วนขยายต้องใช้ autoconf, gcc และส่วนหัวสำหรับการพัฒนา ซึ่งไม่มีสิ่งใดควรอยู่ในสภาพแวดล้อมขณะทำงาน ให้ใช้ตัวติดตั้งในขั้นตอนสำหรับสร้าง จากนั้นคัดลอกไฟล์ .so ที่คอมไพล์แล้วและไฟล์ ini ใน conf.d ที่ตรงกันไปยังขั้นตอนสำหรับทำงานที่สะอาด

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/

ลำดับการแคชเลเยอร์

Docker จะแคชเลเยอร์ตั้งแต่บนลงล่าง และทำให้ทุกเลเยอร์ด้านล่างใช้แคชไม่ได้เมื่อเลเยอร์หนึ่งมีการเปลี่ยนแปลง ให้เรียงจากสิ่งที่เปลี่ยนแปลงน้อยที่สุดไปยังสิ่งที่เปลี่ยนแปลงบ่อยที่สุด:

  • ฐานและส่วนขยาย (ไม่ค่อยเปลี่ยน)
  • composer.lock และการติดตั้ง (เปลี่ยนเป็นครั้งคราว)
  • ซอร์สโค้ดของแอป (ทุกคอมมิต)
  • การสร้างตัวโหลดอัตโนมัติ (ทุกคอมมิต)

ดังนั้น การเปลี่ยนแปลงเฉพาะโค้ดจะนำเลเยอร์ vendor ที่แคชไว้กลับมาใช้ได้ทั้งหมด

# 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

เมื่อใช้ BuildKit (DOCKER_BUILDKIT=1) คุณสามารถเมานต์แคชถาวรที่คงอยู่ข้ามการสร้างแต่ละครั้งได้ โดยไม่ถูกนำไปรวมไว้ในอิมเมจ เหมาะอย่างยิ่งสำหรับแคชส่วนกลางของ Composer เพราะการสร้างซ้ำจะไม่ต้องดาวน์โหลดแพ็กเกจอีกครั้ง

# 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

วัดขนาดอิมเมจ

ตรวจสอบรายละเอียดของแต่ละเลเยอร์เพื่อค้นหาส่วนที่มีขนาดเกินจำเป็น docker history จะแสดงขนาดที่แต่ละคำสั่งเพิ่มเข้ามา ส่วนเครื่องมืออย่าง dive จะแสดงพื้นที่ที่สูญเปล่า เป้าหมายคือขั้นตอนสำหรับทำงานที่ไม่มีคอมไพเลอร์ ไม่มี Composer และไม่มีการอ้างอิงแพ็กเกจสำหรับการพัฒนา

# 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

ลดสิ่งที่อยู่ในขั้นตอนสุดท้าย

ขั้นตอนสำหรับทำงานไม่ควรมี Composer สคริปต์ติดตั้งส่วนขยาย หรือชุดทดสอบของคุณ ขั้นตอนสำหรับสร้างควรคัดลอก vendor และซอร์สโค้ดมาให้ และไม่ควรเรียกใช้ composer ในขั้นตอนสุดท้าย หากจำเป็นต้องเรียกใช้ตัวติดตั้งในขั้นตอนนั้น ให้ลบตัวติดตั้งออกหลังใช้งาน

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"]

ข้อจำกัดของ Distroless / Scratch

PHP ไม่สามารถทำงานบน scratch ที่ว่างเปล่าอย่างแท้จริงได้ เพราะต้องใช้ libc และไลบรารีที่ใช้ร่วมกัน พื้นฐานที่เล็กที่สุดในทางปฏิบัติคือ alpine (ใช้ musl) หรือ Debian แบบเรียบง่ายสไตล์ distroless โดย Alpine มีขนาดเล็กที่สุด แต่ควรระวังไลบรารีเนทีฟที่คาดว่าจะใช้ glibc หากพบข้อผิดพลาด segmentation fault ร่วมกับ NSS/ICU ให้เปลี่ยนไปใช้ 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

กำหนดเป้าหมายของขั้นตอน

Dockerfile เดียวสามารถรองรับทั้งการพัฒนาและการใช้งานจริงผ่าน --target ให้เพิ่มขั้นตอน dev บนขั้นตอนสำหรับทำงาน โดยเพิ่มการอ้างอิงแพ็กเกจสำหรับการพัฒนาใน Composer และ Xdebug กลับเข้าไป จากนั้นสร้างด้วย --target=runtime สำหรับใช้งานจริง และใช้ --target=dev ในเครื่อง

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  .

ทำความเข้าใจขนาดของเลเยอร์

แบบจำลองทางความคิดอย่างง่ายช่วยให้คุณคาดการณ์พฤติกรรมของแคชได้ โค้ด CLI นี้จำลองข้อผิดพลาดที่พบบ่อย ซึ่งทำให้เลเยอร์เติบโตโดยไม่มีขอบเขต เทียบกับแบบที่มีเพดาน เพื่อแสดงให้เห็นว่าเหตุใดการรวมการล้างข้อมูลไว้ใน RUN เดียวกันจึงสำคัญ

<?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";
?>

รวมและล้างข้อมูลใน RUN เดียว

แต่ละ RUN คือหนึ่งเลเยอร์ การลบไฟล์ในเลเยอร์ที่ตามมาไม่ได้ทำให้อิมเมจมีขนาดเล็กลง เพราะเลเยอร์ก่อนหน้ายังคงเก็บไบต์เหล่านั้นไว้ ให้ติดตั้ง ใช้งาน และล้างข้อมูลภายใน RUN เดียวกัน เพื่อไม่ให้ไฟล์ชั่วคราวถูกบันทึกลงในเลเยอร์

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/*

ตรวจสอบอย่างรวดเร็ว

เหตุใดจึงต้องลบการอ้างอิงแพ็กเกจสำหรับการสร้างใน RUN เดียวกับที่ติดตั้งสิ่งเหล่านั้น

สรุปทบทวน

การสร้างแบบหลายขั้นตอนช่วยไม่ให้คอมไพเลอร์และการอ้างอิงแพ็กเกจสำหรับการพัฒนาเข้าไปอยู่ในสภาพแวดล้อมจริง คุณได้เรียนรู้วิธีตั้งชื่อขั้นตอนและใช้ COPY --from เพื่อคัดลอกผลลัพธ์ที่สร้างแล้ว จัดลำดับเลเยอร์จากสิ่งที่เปลี่ยนแปลงน้อยไปมากเพื่อการแคช ใช้จุดติดตั้งแคชของ BuildKit สำหรับ Composer วัดขนาดด้วย docker history/dive เลือก Alpine หรือ glibc อย่างมีเหตุผล กำหนดเป้าหมายขั้นตอนสำหรับการพัฒนาและใช้งานจริง และรวมการติดตั้งกับการล้างข้อมูลไว้ใน RUN เดียว

คำถามที่พบบ่อย

บทเรียน “การสร้างหลายขั้นตอนและการปรับประสิทธิภาพ” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การสร้างหลายขั้นตอนและการปรับประสิทธิภาพ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส PHP Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การสร้างหลายขั้นตอนและการปรับประสิทธิภาพ”

ลดขนาดอิมเมจและแยกขั้นตอนสร้างออกจากการทำงาน คุณปฏิบัติ PHP Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน PHP Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน PHP Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “การสร้างหลายขั้นตอนและการปรับประสิทธิภาพ” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน PHP Academy นี้ได้ไหม

ได้ บทเรียน PHP Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การทำแอปพลิเคชัน PHP ให้เป็นคอนเทนเนอร์
  2. การสร้างหลายขั้นตอนและการปรับประสิทธิภาพ
  3. Docker Compose สำหรับชุดบริการภายในเครื่อง
  4. CI/CD ด้วย GitHub Actions
← กลับไปที่ PHP Academy