หนึ่งในตัวอย่างที่ดีที่สุดสำหรับการเรียนรู้ Docker Compose คือการรัน WordPress + MySQL ซึ่งเป็น Stack ที่ใช้งานจริงในโลก Production ประกอบด้วย 2 Services ที่ต้องสื่อสารกัน มี Volume สำหรับเก็บข้อมูล และต้องกำหนด Environment Variables ให้ถูกต้อง บทความนี้จะพาคุณสร้าง Stack นี้ตั้งแต่ต้นจนเปิดใช้งานได้จริง
โครงสร้างของ WordPress + MySQL Stack
ก่อนเริ่มเขียน docker-compose.yml มาทำความเข้าใจว่า Stack นี้ประกอบด้วยอะไรบ้าง:
- MySQL — ฐานข้อมูลสำหรับ WordPress
- WordPress — แอปพลิเคชันหลัก รัน PHP + Apache
- Volume สำหรับ MySQL เก็บข้อมูล DB ให้คงอยู่แม้ Container หยุด
- Volume สำหรับ WordPress เก็บ wp-content (themes, plugins, uploads)
- Network ให้ทั้งสอง Container คุยกันได้ภายใน
สร้างโฟลเดอร์โปรเจกต์
mkdir wordpress-stack
cd wordpress-stack
เขียนไฟล์ docker-compose.yml
สร้างไฟล์ docker-compose.yml ในโฟลเดอร์ wordpress-stack:
version: '3.8'
services:
db:
image: mysql:8.0
container_name: wordpress_db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wppassword
volumes:
- db_data:/var/lib/mysql
networks:
- wp_network
wordpress:
image: wordpress:latest
container_name: wordpress_app
restart: unless-stopped
depends_on:
- db
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: wppassword
WORDPRESS_DB_NAME: wordpress
volumes:
- wp_data:/var/www/html
networks:
- wp_network
volumes:
db_data:
wp_data:
networks:
wp_network:
driver: bridge
อธิบาย docker-compose.yml แต่ละส่วน
Service: db (MySQL)
| Option | ความหมาย |
|---|---|
image: mysql:8.0 |
ใช้ MySQL เวอร์ชัน 8.0 |
restart: unless-stopped |
รีสตาร์ตอัตโนมัติ ยกเว้นกรณีหยุดเอง |
MYSQL_ROOT_PASSWORD |
รหัส root ของ MySQL (ต้องตั้งเสมอ) |
MYSQL_DATABASE |
ชื่อ Database ที่สร้างอัตโนมัติ |
MYSQL_USER / PASSWORD |
User สำหรับ WordPress ใช้ |
volumes: db_data:/var/lib/mysql |
เก็บข้อมูล DB ให้คงอยู่ |
Service: wordpress
| Option | ความหมาย |
|---|---|
depends_on: db |
รอให้ db Container ขึ้นก่อน |
ports: 8080:80 |
เปิด port 8080 บน Host ไปยัง 80 ใน Container |
WORDPRESS_DB_HOST: db:3306 |
ชี้ไปยัง Service ชื่อ “db” port 3306 |
volumes: wp_data:/var/www/html |
เก็บไฟล์ WordPress (themes, plugins, uploads) |
รัน Stack
# รันในโหมด Detached (Background)
docker compose up -d
# ดู Logs
docker compose logs -f
# ดู Status
docker compose ps
หลังรันคำสั่ง รอประมาณ 30-60 วินาทีให้ MySQL พร้อม แล้วเปิด Browser ไปที่ http://localhost:8080 จะเห็นหน้า WordPress Installation
ทำความเข้าใจ depends_on
depends_on บอกให้ Docker Compose รอให้ Service db เริ่มต้น ก่อน แต่ไม่ได้หมายความว่า MySQL พร้อมรับ Connection แล้ว MySQL ต้องใช้เวลาสักครู่ในการ Initialize ดังนั้น WordPress อาจ Retry การเชื่อมต่อหลายครั้ง ซึ่ง WordPress Image จัดการให้อัตโนมัติ
หากต้องการ Health Check ที่แม่นยำกว่า ให้ใช้:
db:
image: mysql:8.0
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
wordpress:
depends_on:
db:
condition: service_healthy
การจัดการ Stack
# หยุด Stack (ข้อมูลยังอยู่ใน Volume)
docker compose stop
# หยุดและลบ Container (ข้อมูลยังอยู่ใน Volume)
docker compose down
# หยุด + ลบ Container + ลบ Volume (ข้อมูลหาย!)
docker compose down -v
# Restart เฉพาะ Service
docker compose restart wordpress
การ Backup ข้อมูล WordPress
ข้อมูลสำคัญอยู่ใน 2 Volume คือ db_data (ฐานข้อมูล) และ wp_data (ไฟล์ WordPress) วิธี Backup ง่ายๆ:
# Backup MySQL Database
docker compose exec db mysqldump -u wpuser -pwppassword wordpress > backup.sql
# Backup wp-content
docker run --rm \
-v wordpress-stack_wp_data:/source \
-v $(pwd):/backup \
alpine tar czf /backup/wp-content-backup.tar.gz -C /source wp-content
เพิ่ม phpMyAdmin เพื่อจัดการ Database
สามารถเพิ่ม phpMyAdmin เข้าไปใน Stack เพื่อจัดการ Database ผ่าน Web UI:
phpmyadmin:
image: phpmyadmin:latest
container_name: wordpress_pma
restart: unless-stopped
depends_on:
- db
ports:
- "8081:80"
environment:
PMA_HOST: db
PMA_USER: wpuser
PMA_PASSWORD: wppassword
networks:
- wp_network
เปิด http://localhost:8081 เพื่อเข้าใช้ phpMyAdmin
สรุป
| สิ่งที่เรียนรู้ | รายละเอียด |
|---|---|
| Multi-Service Stack | รัน WordPress + MySQL ด้วยไฟล์เดียว |
| Service Discovery | WordPress เชื่อมต่อ MySQL ผ่านชื่อ Service |
| Volume Persistence | ข้อมูลไม่หายแม้ Container หยุด |
| depends_on | ควบคุมลำดับการเริ่มต้น Service |
| Health Check | รอให้ Service พร้อมจริงก่อนเชื่อมต่อ |
บทความถัดไป เราจะเรียนรู้เรื่อง Environment Variables และ .env File ซึ่งเป็นวิธีที่ดีกว่าการเขียน Password ตรงๆ ใน docker-compose.yml และเป็น Best Practice ที่ทุก DevOps ต้องรู้

