Docker Compose สำหรับชุดบริการภายในเครื่อง
เรียกใช้ PHP ฐานข้อมูล และแคชร่วมกันภายในเครื่อง
Docker Compose สำหรับชุดบริการภายในเครื่อง เป็นบทเรียน PHP Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน PHP Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน
สแตกในเครื่องด้วย Compose
แอป PHP จริงไม่เคยมีแค่ PHP เพราะต้องใช้ฐานข้อมูล แคช และบางครั้งยังต้องใช้คิวกับตัวดักอีเมลด้วย Docker Compose จะประกาศสิ่งเหล่านี้เป็นบริการต่าง ๆ ในไฟล์เดียว และเชื่อมบริการทั้งหมดเข้ากับเครือข่ายร่วม เพื่อให้บริการเหล่านั้นเข้าถึงกันได้ด้วยชื่อ
บทเรียนนี้จะสร้างสแตกในเครื่องแบบครบชุด ได้แก่ PHP-FPM + nginx + MySQL + Redis พร้อมโวลุม การตรวจสอบสุขภาพ และการจัดลำดับการพึ่งพา
โครงสร้างบริการ
ไฟล์ Compose จะแสดงรายการบริการไว้ภายใต้ services: แต่ละบริการสามารถ build จาก Dockerfile หรือดึง image มาใช้ได้ Compose จะสร้างเครือข่ายเริ่มต้นซึ่งทุกบริการเข้าถึงได้ด้วยคีย์ของบริการนั้น ๆ โดยแอป PHP ของคุณจะเชื่อมต่อกับ MySQL ที่โฮสต์ db ไม่ใช่ localhost
services:
app:
build:
context: .
target: dev # multi-stage dev target
volumes:
- ./:/app # live code mount
depends_on:
db:
condition: service_healthy
db:
image: mysql:8.4
redis:
image: redis:7-alpineวาง nginx ไว้ด้านหน้า FPM
FPM สื่อสารด้วย FastCGI ที่พอร์ต 9000 ไม่ใช่ HTTP nginx จะรับการเชื่อมต่อ HTTP และส่งคำขอ .php ต่อไปยัง app:9000 การกำหนดค่า nginx จะอ้างอิงบริการ PHP ด้วยชื่อ Compose ของบริการนั้น
# docker/nginx/default.conf
server {
listen 80;
root /app/public;
index index.php;
location / {
try_files $uri /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000; # service name from compose
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}เชื่อมต่อบริการเว็บ
บริการ nginx จะเมานต์โค้ดชุดเดียวกันเพื่อแก้ค่า SCRIPT_FILENAME รวมถึงไฟล์การกำหนดค่า เปิดให้เข้าถึงพอร์ต 80 และกำหนดให้ขึ้นต่อกับแอป ทั้งสองบริการใช้ /app ร่วมกัน เพื่อให้เส้นทางตรงกันทั้งสองฝั่งของ FastCGI
services:
web:
image: nginx:1.27-alpine
ports:
- "8080:80"
volumes:
- ./:/app:ro
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- appโวลุมถาวร
ระบบไฟล์ของคอนเทนเนอร์เป็นแบบชั่วคราว โวลุมที่มีชื่อจะเก็บไฟล์ฐานข้อมูลไว้ต่อเนื่องแม้เรียกใช้ docker compose down ส่วนการเมานต์แบบผูก (./:/app) จะซิงค์โค้ดจากเครื่องให้เห็นการเปลี่ยนแปลงแบบสด ๆ ในระหว่างการพัฒนา ให้ใช้โวลุมที่มีชื่อสำหรับข้อมูลที่ต้องคงอยู่ และใช้การเมานต์แบบผูกสำหรับซอร์สโค้ด
services:
db:
image: mysql:8.4
environment:
MYSQL_DATABASE: app
MYSQL_USER: app
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: rootsecret
volumes:
- dbdata:/var/lib/mysql
volumes:
dbdata: # survives `down`, removed only by `down -v`การตรวจสอบสุขภาพและ depends_on
depends_on เพียงอย่างเดียวจะรอแค่ให้คอนเทนเนอร์ เริ่มทำงาน ไม่ได้รอให้ MySQL ยอมรับการเชื่อมต่อ ให้เพิ่ม healthcheck และใช้ condition: service_healthy เพื่อให้แอปของคุณรอจนกว่าฐานข้อมูลจะพร้อมใช้งานจริง
services:
db:
image: mysql:8.4
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-prootsecret"]
interval: 5s
timeout: 3s
retries: 10
app:
build: .
depends_on:
db:
condition: service_healthy # waits for healthcheck passสภาพแวดล้อมและ .env
Compose จะโหลด .env ที่อยู่ในโฟลเดอร์เดียวกันโดยอัตโนมัติเพื่อแทนค่าตัวแปร และคุณสามารถส่งการกำหนดค่าแอปผ่าน environment หรือ env_file ได้ อย่าเก็บข้อมูลลับไว้ในไฟล์ Compose ที่คอมมิตแล้ว แต่ให้อ้างอิงตัวแปรแทน
services:
app:
build: .
env_file:
- .env
environment:
DATABASE_URL: "mysql://app:secret@db:3306/app"
REDIS_URL: "redis://redis:6379"
# .env (gitignored) provides ${...} substitutions
# MYSQL_PASSWORD=secretเชื่อมต่อจาก PHP
ภายในเครือข่าย ชื่อโฮสต์จะเป็นชื่อบริการ โค้ด PHP ของคุณจึงเชื่อมต่อกับ db และ redis ได้โดยตรง ตัวอย่างนี้แยกวิเคราะห์ DSN ในลักษณะเดียวกับที่ชั้นการกำหนดค่าจะทำ เพื่อแสดงให้เห็นว่าชื่อบริการของ Compose ถูกส่งต่อเข้าไปในสตริงการเชื่อมต่ออย่างไร
<?php
$dsn = 'mysql://app:secret@db:3306/app';
$p = parse_url($dsn);
printf("driver: %s\n", $p['scheme']);
printf("host: %s\n", $p['host']); // 'db' resolves via compose DNS
printf("port: %d\n", $p['port']);
printf("db: %s\n", ltrim($p['path'], '/'));
$pdoDsn = sprintf('mysql:host=%s;port=%d;dbname=%s', $p['host'], $p['port'], ltrim($p['path'], '/'));
echo $pdoDsn . PHP_EOL;
?>Xdebug สำหรับการพัฒนาในเครื่อง
ให้เมานต์การกำหนดค่า Xdebug เฉพาะในเครื่องผ่านเป้าหมายการสร้าง dev กำหนด client_host เป็น host.docker.internal เพื่อให้ตัวดีบักเชื่อมต่อไปยังเครื่องมือพัฒนาของคุณบนโฮสต์ได้ อย่าส่ง Xdebug ไปยังสภาพแวดล้อมจริง เพราะจะทำให้ประสิทธิภาพลดลงอย่างมาก
; docker/php/xdebug.ini (mounted only in dev)
zend_extension=xdebug
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9003เรียกใช้คำสั่งครั้งเดียว
docker compose run จะสร้างคอนเทนเนอร์ชั่วคราวสำหรับการย้ายข้อมูล การทดสอบ หรือการเรียกใช้ Composer ส่วน exec จะทำงานภายในบริการที่กำลังทำงานอยู่แล้ว ให้ใช้ run --rm สำหรับงานเหล่านี้ เพื่อให้คอนเทนเนอร์ชั่วคราวถูกล้างออก
# Run migrations against the running db
docker compose exec app php bin/console doctrine:migrations:migrate
# One-off: install deps without a long-lived container
docker compose run --rm app composer install
# Tail logs of just the web service
docker compose logs -f webไฟล์แทนที่
Compose จะผสาน docker-compose.yml กับ docker-compose.override.yml โดยอัตโนมัติ ให้เก็บค่าเริ่มต้นที่มีโครงสร้างเหมือนสภาพแวดล้อมจริงไว้ในไฟล์ฐาน และใส่โวลุม พอร์ต และ Xdebug ที่ใช้เฉพาะการพัฒนาไว้ในไฟล์แทนที่ เพื่อให้ CI ใช้ไฟล์ฐาน และนักพัฒนาได้รับส่วนเพิ่มเติมโดยไม่ต้องตั้งค่าเพิ่ม
# docker-compose.override.yml (auto-merged, dev only)
services:
app:
volumes:
- ./docker/php/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini:ro
environment:
APP_ENV: dev
# CI runs: docker compose -f docker-compose.yml up (no override)ตรวจสอบอย่างรวดเร็ว
เหตุใด depends_on: [db] แบบธรรมดาจึงไม่เพียงพอก่อนเรียกใช้การย้ายข้อมูล
สรุปทบทวน
คุณประกอบสแตกในเครื่องด้วย Compose: PHP-FPM ที่อยู่หลัง nginx (FastCGI ไปยัง app:9000) MySQL และ Redis ที่เข้าถึงได้ด้วยชื่อบริการ โวลุมที่มีชื่อสำหรับเก็บข้อมูลถาวร การตรวจสอบสุขภาพเพื่อควบคุม depends_on การกำหนดค่าที่ขับเคลื่อนด้วย env, Xdebug ในไฟล์แทนที่ที่ใช้เฉพาะการพัฒนา และคำสั่งครั้งเดียวผ่าน run/exec
โปรดจำ: ชื่อบริการคือชื่อโฮสต์ DNS ไฟล์แทนที่ช่วยแยกส่วนเพิ่มเติมสำหรับการพัฒนาออกจาก CI และการตรวจสอบสุขภาพมีประสิทธิภาพกว่าการจัดลำดับการเริ่มทำงานแบบง่าย ๆ
คำถามที่พบบ่อย
บทเรียน “Docker Compose สำหรับชุดบริการภายในเครื่อง” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “Docker Compose สำหรับชุดบริการภายในเครื่อง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส PHP Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “Docker Compose สำหรับชุดบริการภายในเครื่อง”
เรียกใช้ PHP ฐานข้อมูล และแคชร่วมกันภายในเครื่อง คุณปฏิบัติ PHP Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน PHP Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน PHP Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “Docker Compose สำหรับชุดบริการภายในเครื่อง” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน PHP Academy นี้ได้ไหม
ได้ บทเรียน PHP Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การทำแอปพลิเคชัน PHP ให้เป็นคอนเทนเนอร์
- การสร้างหลายขั้นตอนและการปรับประสิทธิภาพ
- Docker Compose สำหรับชุดบริการภายในเครื่อง
- CI/CD ด้วย GitHub Actions