ในโลกของการพัฒนาซอฟต์แวร์ ปัญหาคลาสสิกที่นักพัฒนารับมือมาตลอดคือ "It works on my machine!" ปัญหานี้ไม่ได้มาจากตรรกะของโค้ด (Business Logic) แต่มาจากความไม่เข้ากันของสภาพแวดล้อมในการทำงาน (Environment Inconsistency) ไม่ว่าจะเป็นเวอร์ชัน PHP ที่แตกต่างกัน, ส่วนขยาย (Extensions) ที่ขาดหายไป, หรือการตั้งค่า Web Server และฐานข้อมูลที่ต่างกันระหว่างเครื่อง Local, Staging, และ Production
การจัดการความแตกต่างเหล่านี้ด้วยตนเองเป็นเรื่องที่ซับซ้อนและกินเวลาอย่างมาก จนกระทั่งแนวคิด Containerization และ Docker เข้ามาปฏิวัติวงการ
Docker: กุญแจสู่สภาพแวดล้อมที่เหมือนกันทุกที่
Docker ช่วยให้เราสามารถสร้าง "กล่องเสมือน" (Container) ที่บรรจุทุกสิ่งจำเป็นที่โปรเจกต์ต้องการให้ทำงานได้อย่างสมบูรณ์และเป็นอิสระจากระบบปฏิบัติการโฮสต์ภายนอก แทนที่จะติดตั้ง PHP, Nginx, และ PostgreSQL ลงบนเครื่องเดียวกัน เราจะกำหนดให้แต่ละส่วนประกอบเป็นบริการ (Service) แยกกัน
หลักการทำงานด้วย Docker Compose
หัวใจสำคัญของการจัดการสภาพแวดล้อมที่ซับซ้อนคือการใช้ docker-compose.yml ซึ่งทำหน้าที่เป็นพิมพ์เขียว (Blueprint) ที่ระบุว่าบริการทั้งหมด (PHP-FPM, Web Server, PostgreSQL) ต้องทำงานร่วมกันอย่างไร โดยที่ทุกบริการจะทำงานแยกกันแต่สื่อสารกันผ่านเครือข่ายภายในของ Docker
ในกรณีของ PHP ที่ต้องเชื่อมต่อกับ PostgreSQL เราจะต้องมั่นใจว่า:
- PHP-FPM Service: ถูกกำหนดให้ใช้ PHP เวอร์ชันที่ต้องการ พร้อมติดตั้งส่วนขยาย PostgreSQL (เช่น
pdo_pgsql) - PostgreSQL Service: ถูกรันเป็น Container แยกต่างหาก พร้อมกำหนด Environment Variables สำหรับรหัสผ่านและชื่อฐานข้อมูล
- Web Server (Nginx): ถูกตั้งค่าให้ส่งต่อคำขอ (Proxy) ไปยัง PHP-FPM Container
ตัวอย่างโครงสร้าง docker-compose.yml สำหรับโปรเจกต์ PHP/PostgreSQL:
YAML
version: '3.8'\nservices:\n php: # PHP-FPM Service\n image: php:8.2-fpm-alpine\n volumes: - ./src:/var/www/html\n depends_on: - db\n nginx:\n image: nginx:alpine\n volumes: - ./src:/var/www/html\n ports: - "80:80"\n depends_on: - php\n db: # PostgreSQL Service\n image: postgres:15-alpine\n environment:\n POSTGRES_DB: myapp_db\n POSTGRES_USER: devuser\n POSTGRES_PASSWORD: securepassword\n volumes: - postgres_data:/var/lib/postgresql/data\n
การทดสอบการเชื่อมต่อ (PostgreSQL)
เมื่อทุกบริการทำงานพร้อมกัน นักพัฒนาสามารถใช้คำสั่ง docker exec เพื่อเข้าถึง Container ของ PostgreSQL และทดสอบการเชื่อมต่อฐานข้อมูลได้ทันที โดยไม่ต้องพึ่งพาการตั้งค่าเครือข่ายที่ซับซ้อน
SQL
docker exec -it <container_id_db> psql -U devuser -d myapp_db;
จากนั้นภายใน psql prompt คุณสามารถรันคำสั่ง SQL เพื่อตรวจสอบความพร้อมของฐานข้อมูลได้:
SQL
SELECT version();
บทสรุป
การใช้ Docker ทำให้การพัฒนา PHP ที่ต้องพึ่งพา PostgreSQL มีความเสถียรและสามารถทำซ้ำได้ (Reproducible) อย่างสมบูรณ์แบบ ไม่ว่าคุณจะทำงานบนเครื่อง Mac, Windows, หรือ Linux สภาพแวดล้อมการทำงานก็จะเหมือนกันทุกประการ ทำให้ทีมพัฒนาลดเวลาในการแก้ไขปัญหาด้าน Environment และโฟกัสไปที่การพัฒนา Business Logic ได้อย่างเต็มที่