Docker Compose: จัดการ Multi-Container Application
ในบทที่แล้ว เราได้เรียนรู้วิธีการสร้างและรัน Docker Container ทีละ Container ด้วยคำสั่ง docker run ซึ่งเป็นวิธีที่ใช้งานได้ดีสำหรับแอปพลิเคชันขนาดเล็ก แต่เมื่อแอปพลิเคชันของเราซับซ้อนขึ้น มีหลาย Container ที่ต้องทำงานร่วมกัน การจัดการ Container เหล่านั้นด้วยคำสั่ง docker run ทีละตัวจะกลายเป็นเรื่องที่ยุ่งยากและเสียเวลาอย่างมาก
Docker Compose เข้ามาช่วยแก้ปัญหานี้ Docker Compose เป็นเครื่องมือที่ช่วยให้เราสามารถกำหนดค่าและจัดการ Multi-Container Application ได้อย่างง่ายดาย โดยการใช้ไฟล์ docker-compose.yml เพื่อกำหนด Container ทั้งหมดที่แอปพลิเคชันของเราต้องการ รวมถึง dependencies, networks, volumes และ configuration อื่นๆ
ทำไมต้อง Docker Compose?
- Simplified Management: ช่วยให้การจัดการ Multi-Container Application ง่ายขึ้น โดยการกำหนดค่าทั้งหมดในไฟล์เดียว
- Repeatable Environments: สร้างสภาพแวดล้อมที่เหมือนกันได้ง่ายๆ ไม่ว่าจะเป็น development, staging หรือ production
- Collaboration: ทำให้การทำงานร่วมกันในทีมง่ายขึ้น ทุกคนสามารถเข้าใจและรันแอปพลิเคชันได้ด้วยไฟล์
docker-compose.ymlเพียงไฟล์เดียว
docker-compose.yml คืออะไร?
docker-compose.yml เป็นไฟล์ YAML ที่ใช้กำหนด Container ทั้งหมดที่แอปพลิเคชันของเราต้องการ รวมถึง dependencies, networks, volumes และ configuration อื่นๆ ไฟล์นี้จะเป็นตัวกำหนดวิธีการสร้างและรัน Container ทั้งหมด
โครงสร้างพื้นฐานของไฟล์ docker-compose.yml มีลักษณะดังนี้:
version: "3.9" # กำหนด version ของ Docker Compose file format
services:
web: # ชื่อของ service (Container)
image: php:8.1-apache # Docker image ที่ใช้
ports:
- "80:80" # Map port 80 ของ host ไปยัง port 80 ของ Container
volumes:
- ./app:/var/www/html # Mount volume จาก host ไปยัง Container
depends_on: # กำหนด dependencies ของ service นี้
- db
db: # ชื่อของ service (Container)
image: mysql:5.7 # Docker image ที่ใช้
environment:
MYSQL_ROOT_PASSWORD: password # กำหนด environment variable
volumes:
- db_data:/var/lib/mysql # Mount named volume
volumes:
db_data: # กำหนด named volume
คำอธิบายส่วนประกอบหลัก:
version: กำหนด version ของ Docker Compose file format ควรใช้ version ที่ใหม่ที่สุดที่ Docker Engine ของคุณรองรับservices: ส่วนที่กำหนด Container ทั้งหมดที่แอปพลิเคชันของเราต้องการ แต่ละ service จะแทน Container หนึ่งตัวimage: Docker image ที่ใช้สร้าง Containerports: Map port จาก host ไปยัง Container เพื่อให้สามารถเข้าถึง Container ได้จากภายนอกvolumes: Mount volume จาก host ไปยัง Container หรือใช้ named volume เพื่อให้ข้อมูลคงอยู่แม้ Container จะถูกลบdepends_on: กำหนด dependencies ของ service หนึ่งไปยังอีก service หนึ่ง Docker Compose จะเริ่มต้น service ที่เป็น dependency ก่อนenvironment: กำหนด environment variables ที่จะถูกส่งไปยัง Container
Services
Services เป็นส่วนที่สำคัญที่สุดในไฟล์ docker-compose.yml แต่ละ service จะแทน Container หนึ่งตัว และกำหนดค่าต่างๆ ที่เกี่ยวข้องกับ Container นั้น
ตัวอย่าง:
services:
web:
image: php:8.1-apache
ports:
- "80:80"
volumes:
- ./app:/var/www/html
depends_on:
- db
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: password
volumes:
- db_data:/var/lib/mysql
ในตัวอย่างนี้ เรามี 2 services คือ web และ db service web ใช้ image php:8.1-apache และ map port 80 service db ใช้ image mysql:5.7 และกำหนด environment variable MYSQL_ROOT_PASSWORD
Networks
Docker Compose จะสร้าง network default ให้โดยอัตโนมัติ เพื่อให้ Container ทั้งหมดใน Compose file สามารถสื่อสารกันได้ หากต้องการกำหนดค่า network เอง สามารถทำได้โดยการกำหนดในส่วน networks
ตัวอย่าง:
version: "3.9"
services:
web:
image: php:8.1-apache
ports:
- "80:80"
volumes:
- ./app:/var/www/html
depends_on:
- db
networks:
- my_network
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: password
volumes:
- db_data:/var/lib/mysql
networks:
- my_network
networks:
my_network:
driver: bridge
ในตัวอย่างนี้ เราได้สร้าง network ชื่อ my_network และกำหนดให้ทั้ง web และ db services ใช้ network นี้
Volumes
Volumes ใช้สำหรับเก็บข้อมูลแบบ persistent ใน Docker ข้อมูลที่เก็บใน volume จะไม่หายไปแม้ Container จะถูกลบ Docker Compose สนับสนุนทั้ง bind mounts และ named volumes
Bind Mounts:
services:
web:
image: php:8.1-apache
volumes:
- ./app:/var/www/html # Mount directory ./app จาก host ไปยัง /var/www/html ใน Container
Named Volumes:
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql # Mount named volume db_data ไปยัง /var/lib/mysql ใน Container
volumes:
db_data: # กำหนด named volume
Named volumes จะถูกจัดการโดย Docker และเก็บข้อมูลใน directory ที่ Docker กำหนด
การใช้งาน Docker Compose
หลังจากที่เราสร้างไฟล์ docker-compose.yml แล้ว เราสามารถใช้คำสั่ง docker-compose เพื่อจัดการ Container ทั้งหมดได้
docker-compose up: สร้างและรัน Container ทั้งหมดที่กำหนดในไฟล์docker-compose.ymldocker-compose down: หยุดและลบ Container ทั้งหมดที่สร้างโดยdocker-compose updocker-compose ps: แสดงสถานะของ Container ทั้งหมดdocker-compose logs: แสดง logs ของ Containerdocker-compose exec: รันคำสั่งภายใน Container
ตัวอย่างการใช้งาน:
- สร้าง directory สำหรับโปรเจกต์ของคุณ:
mkdir my-app - เข้าไปใน directory:
cd my-app - สร้างไฟล์
docker-compose.ymlและใส่ configuration ตามตัวอย่างข้างต้น - รันคำสั่ง
docker-compose up -dเพื่อสร้างและรัน Container ใน detached mode (background) - เปิด browser และเข้าถึง
localhostเพื่อดูแอปพลิเคชันของคุณ - เมื่อต้องการหยุดและลบ Container ให้รันคำสั่ง
docker-compose down
กรณีใช้งานจริงและข้อผิดพลาดที่พบบ่อย
กรณีใช้งานจริง:
สมมติว่าเรามีแอปพลิเคชัน PHP ที่ต้องใช้ MySQL database และ Redis cache เราสามารถสร้างไฟล์ docker-compose.yml ที่กำหนด Container ทั้งหมดนี้ได้
version: "3.9"
services:
web:
image: php:8.1-apache
ports:
- "80:80"
volumes:
- ./app:/var/www/html
depends_on:
- db
- redis
environment:
DB_HOST: db
DB_USER: root
DB_PASSWORD: password
REDIS_HOST: redis
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: password
volumes:
- db_data:/var/lib/mysql
redis:
image: redis:latest
volumes:
db_data:
ในตัวอย่างนี้ เรามี 3 services คือ web, db และ redis service web ขึ้นอยู่กับ db และ redis Docker Compose จะเริ่มต้น db และ redis ก่อนที่จะเริ่มต้น web
ข้อผิดพลาดที่พบบ่อย:
- Syntax errors ในไฟล์
docker-compose.yml: ตรวจสอบให้แน่ใจว่าไฟล์docker-compose.ymlของคุณถูกต้องตาม syntax ของ YAML - Port conflicts: ตรวจสอบให้แน่ใจว่า port ที่คุณ map ไม่ได้ถูกใช้งานโดย application อื่นบน host ของคุณ
- Database connection errors: ตรวจสอบให้แน่ใจว่า environment variables ที่ใช้ในการเชื่อมต่อ database ถูกต้อง
- Volume mount errors: ตรวจสอบให้แน่ใจว่า directory ที่คุณ mount มีอยู่บน host ของคุณ
สรุป
Docker Compose เป็นเครื่องมือที่สำคัญสำหรับนักพัฒนา PHP ที่ต้องการจัดการ Multi-Container Application อย่างมีประสิทธิภาพ ช่วยให้การสร้าง, รัน, และจัดการ Container ง่ายขึ้น ทำให้เราสามารถโฟกัสไปที่การพัฒนาแอปพลิเคชันได้มากขึ้น ในบทถัดไป เราจะเรียนรู้เกี่ยวกับการจัดการข้อมูลแบบ persistent ใน Docker โดยใช้ Volumes