[PHP x Container] ทบทวนการย้าย PHP Web Application มาทำงานบน Container

เมื่อเราต้องย้ายบ้าน จาก Host มาเป็น Container แต่ PHP บน Container มันก็เรื่องเยอะเหลือเกิน ยังดีที่หลายอย่างทำได้ง่ายกว่าทำ Host เองนะ

Siwawes Wongcharoen
3 min readJul 17, 2022

ใน Blog นี้ จะเป็นเรื่องการทบทวน การย้าย PHP Web Application จาก Host มาเป็น Container ว่ามีอะไรบ้างที่ควรรู้ สิ่งที่ต้องทำ และเกร็ดเล็กเกร็ดน้อย ที่ได้มาจากการลงมือทำครับ

Docker Build with ARG Command

LAMP/LEMP Stack (Linux, Apache/Nginx, MySQL, PHP)

[https://www.nipa.cloud/blog/lemp-program-dev]

สรุปง่าย ๆ LAMP/LEMP ก็คือเช็ตของ Open Source ที่ใช้ประกอบกันเพื่อสร้าง Web Application ขึ้นมานั่นเอง

  • L (Linux) คือ OS
  • A/E (Apache httpd/Nginx) คือ Web Server ถ้าเป็นภาษาในสมัยนี้ จะมี Web Server มาในตัวเลย ไม่จำเป็นต้องใช้ตัวแยกแบบเมื่อก่อนแล้ว
  • M (MySQL) คือ Database ในสมัยนี้ก็ไม่จำเป็นแล้ว ว่าต้องเป็น MySQL เนื่องจากเรามีทางเลือกมากขึ้น ควรเน้นใช้ให้เหมาะกับงาน จะดีที่สุด
  • P (PHP) คือ Runtime ที่เราใช้งาน

LAMP Stack on Container

เนื่องจากผมชอบที่จะให้ Stack Linux, Apache, PHP ทำงานได้บน Image ตัวเดียว ดังนั้นจึงเลือกใช้ Image php:apache เป็นหลัก

สำหรับสาย PHP คงเข้าใจดีกว่า นอกจากตัว Web Server แล้ว PHP Extension และ Configuration ก็สำคัญไม่แพ้กันครับ

Extension

เรื่อง Extension นี่แหละที่จะน่าปวดหัวหน่อย เพราะเราต้องปรับนุ่นปรับนี่ ปรับทีนึงก็จะต้องลอง Build Image ใหม่ทีนึง ตรงนี้ถึงแม้ว่า Docker Build จะช่วย Cache Layer ไว้ใช้ แต่สิ่งที่เราเปลี่ยนมันอยู่ใน Layer เดียวกัน ฉะนั้น Cache จึงไม่ได้ช่วยอะไรเรา

เข้าเรื่องกันดีกว่า

ถ้าใช้ PHP Official Image ทางทีมได้เตรียม คำสั่งสำเร็จมาให้แล้วครับ ใช้งานได้สะดวกมาก มีตัวอย่างการใช้งานมาให้เสร็จ ใช้เวลาศึกษาไม่นานก็เข้าใจได้ครับ

Configuration

ถ้าใช้ PHP Official Image ทางทีมได้เตรียมไฟล์ php.ini มาให้ 2 แบบ คือ php.ini-development และ php.ini-productionโดยค่าเริ่มต้น จะเป็นแบบที่เหมาะกับ Development แต่เราสามารถเปลี่ยนเป็นแบบ Production ได้ รวมถึงจะใช้แบบที่เรา Config เองก็ได้เช่นกันครับ

ลงมือกันดีกว่า

Basic Image and Container

สร้าง Image อย่างง่าย เริ่มกันที่ สร้างไฟล์ Dockerfile ก่อนครับ

อธิบาย

บรรทัดที่ 1 เราเลือก Base Image มาจาก php:apache ตัวนี้จะมี Apache มาในตัวแล้ว พร้อมใช้งานได้เลยครับ

บรรทัดที่ 3 Copy ไฟล์ทั้งหมด จาก Folder src ไปไว้ที่ /var/www/html/ ใน Image

ใน Folder src เราทำไว้แค่ไฟล์เดียวก่อนครับ คือ index.php หน้าตาแบบนี้

จากนั้น เราจะลอง Build Image และ Run container ขึ้นมา จาก Image ที่เราสร้างไว้ครับ ด้วยคำสั่ง

docker build -t php-blog .
docker run -d --name php-blog -p 80:80 php-blog

ถ้าไม่มีปัญหาอะไร เราควรจะได้ Container ที่ทำงานได้แล้ว ใน Container จะมี Apache httpd ทำงานอยู่ ลองเปิด Browser ดู ควรจะเห็นลักษณะนี้ครับ

Hello PHP 8.1.8

เปิดใช้งาน MySQL Extension

จากขั้นตอนที่ผ่านมา โดยพื้นฐานแล้ว MySQL Extension จะยังไม่ได้ถูกเปิดการใช้งานไว้ เราต้องเปิดเอง ด้วยการปรับไฟล์ Dockerfile นิดหน่อยครับ

อธิบาย

บรรทัดที่ 3 จะใช้คำสั่ง docker-php-ext-install ที่ทางผู้พัฒนา Image ตัวนี้ได้เตรียมไว้ให้ เพื่อติดตั้งและเปิดใช้งาน Extension mysqli และ pdo_mysql เพิ่มเติมครับ

จากนั้น เราจะลอง Build Image และ Run container ขึ้นมา จาก Image ที่เราสร้างไว้ครับ (อย่าลืมลบ Container ตัวเก่าก่อน)

จาก phpinfo() ตอนนี้เราจะเห็น Extension mysqli และ pdo_mysql แสดงขึ้นมาแล้ว

Hello mysqli and pdo_mysql extension

ปรับแต่ง Configuration ให้เหมาะกับ Production

ทางผู้พัฒนา Image ตัวนี้ได้เตรียม php.ini มาให้แล้วครับ โดยพื้นฐานจะใช้ php.ini-development แต่เราสามารถเลือกใช้ php.ini-production แทนได้ด้วย

จุดต่างที่จะเห็นได้ชัดที่สุด ระหว่าง php.ini-development กับ php.ini-production จะเป็นเรื่องการแสดง Error ครับ ใน Blog นี้ เราจะใช้จุดนี้เป็นตัวชี้วัดการสลับไฟล์ php.ini-development กับ php.ini-production ว่าเราทำได้ถูกต้องหรือไม่ครับ

แน่นอนว่าเราจะต้องปรับแต่งตัวไฟล์ Dockerfile กันนะครับ

อธิบาย

บรรทัดที่ 3 จะใช้คำสั่ง ARG เพื่อรับค่าตอนที่สั่ง docker build และยังกำหนดค่าเริ่มต้นดักไว้ด้วย

บรรทัดที่ 7 จะเลือกไฟล์ php.ini มาใช้ ระหว่าง php.ini-development กับ php.ini-production จะขึ้นอยู่กับค่า ARG ที่ส่งเข้ามาครับ

ปล. ใครเอาตรงนี้ไปใช้แบบไม่ระวัง ต้องระวังชีวิตเปลี่ยนนะครับ

และเพื่อให้เห็นความแตกต่างอย่างชัดเจน เราจะสร้างไฟล์ที่ตั้งใจให้เกิด Error ขึ้นมาครับ

จากนั้น เราจะลอง Build Image และ Run container ขึ้นมา จาก Image ที่เราสร้างไว้ครับ (อย่าลืมลบ Container ตัวเก่าก่อน)

คำสั่ง Build Image ตอนนี้จะมี 2 ทางเลือก คือ การ Build Image สำหรับ non-production กับ production ครับ

non-production

docker build -t php-blog .
Error from non-production build

production

docker build -t php-blog --build-arg env=production .
Error from production build

จะเห็นได้ว่าการแสดง Error จะต่างกันอย่างชัดเจนระหว่าง php.ini-development กับ php.ini-production นะครับ

พร้อมใช้งานในระดับเบื้องต้นแล้ว

มาถึงจุดที่ก็ถือว่าพร้อมใช้งานในระดับเบื้องต้นแล้วครับ สามารถใช้งานทดแทน LAMP/LEMP Stack ได้แน่นอน

--

--

No responses yet