รัน WordPress + MySQL ด้วย Docker Compose ฉบับสมบูรณ์

หนึ่งในตัวอย่างที่ดีที่สุดสำหรับการเรียนรู้ 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 ต้องรู้