บันทึกนักพัฒนา: Docker Container 101 แล้วเราจะคิดถึงนายนะ WAMP, XAMPP, …

Siwawes Wongcharoen
4 min readJun 2, 2018

เมื่อก่อนนี้ ชาว PHP Web Developer ส่วนใหญ่ น่าจะผ่านร้อนผ่านหนาวกับ Web Development Package ชื่อดัง ตัวใดตัวหนึ่งมาพอสมควร ไม่ว่าจะเป็น App serv, WAMP หรือ XAMPP และตัวอื่นๆที่ไม่ได้กล่าวถึง

หลายๆ คน น่าจะได้สัมผัสประสบการณ์คลาสสิกที่ว่า ทำไมเครื่อง Dev เว็บทำงานได้ แต่บนเครื่อง Production ทำงานไม่ได้ ปัญหานี้มีสาเหตุมาจาก มีอะไรบางอย่างที่แตกต่างกันไป ไม่ว่าจะเป็นเรื่อง PHP version หรือจะเป็นเรื่องการเปิดใช้ PHP Extension ไม่เท่ากัน

หรือจะเป็นเรื่อง เครื่อง Dev เป็น PHP version 7 แต่เครื่องที่เป็น Production ดันใช้ PHP version 5.4 ก็ทำให้อะไรหลายๆ อย่างใช้ไม่ได้บนเครื่อง Production เช่น MySQLi กับ MySQL

เครื่องต่างกัน ย่อมมีอะไรๆ ไม่เท่ากัน

หนักยิ่งไปกว่านั้น คือวิธีการ Deploy ตัว Application เช่นถ้าหากใน Project เราใช้ Component ที่ได้มาจาก Composer แต่เราสั่ง composer install บนเครื่องปลายทางไม่ได้

ไม่มีสิทธิ์ทำอะไรบนเครื่อง Server

นี่ยังไม่รวมเรื่องการ Run Application หลายๆ ตัว ในเครื่องเดี๋ยวกัน จริงอยู่ว่า พวก Apache หรือ NGINX สามารถทำ Virtual host ได้ แต่การจะทำให้ Virtual host แต่ละตัว สามารถใช้ PHP ที่ต่างกันได้ มันไม่ง่ายเลยครับ

Config ซับซ้อน

ภาพจาก https://blogs.msdn.microsoft.com/freddyk/2017/10/31/what-is-docker-what-are-containers/

Docker Container ช่วยคุณได้

เข้าเรื่องกันดีกว่าครับ หลักการของ Docker Container ง่ายคือ ถ้าเราสามารถทำ Container X ให้ทำงานได้บนเครื่อง A แน่ๆ เราจะสามารถเอา Container A ไปทำงานบนเครื่องอื่นๆ แล้วได้ผลแบบเดียวกันกับเครื่อง A ชัวๆ

ข้อดีจุดนี้ของ Docker Container ช่วยเราได้มากครับ ในการณีของ PHP Application เราจะไม่โดนปัญหาเรื่อง Environment ไม่ตรงกันอีกเลย

ฉะนั้นเนื้อหาใน Blog นี้ จะเน้นไปที่การทำ Conntainer ให้ใช้งาน PHP Application ได้นะครับ

ภาพจาก http://itravel.life/dropbox-power-travel-tips/

เนื้อหาจากจุดนี้เป็นต้นไปจะ Technincal ในระดับปานกลางขึ้นไปนะครับ

PHP Web Application

เรามาเริ่มกันที่องค์ประกอบพื้นฐานของการสร้าง PHP Web Application กันก่อนนะครับ

  • Web Server
  • PHP Runtime

ส่วนเรื่อง Database หรืออื่นๆ ผมถือว่าไม่องค์ประกอบหลักนะครับ

Web Server

ขั้นต่ำสุดของการทำ PHP Web Application คือต้องมี Web Server คอยเอาไว้รับ Request ต่างๆ ในตอนนี้ Web server ที่ดังๆ และดีๆ ก็จะมีอยู่แค่ Apache HTTP Server และ NGINX ครับ

ภาพจาก https://www.digitalocean.com/community/tutorials/apache-vs-nginx-practical-considerations

PHP Runtime

ณ วันที่เขียน Blog นี้ (๒ มิถุนายน ๒๕๖๑) ตัว PHP Version ใหม่สุดจะอยู่ที่ 7.2.6 แล้วนะครับ

ลงมือทำ

เป้าหมายของ Blog คือ จะสร้าง Docker Image ขึ้นมา โดยที่ Image ตัวนี้จะสามารถใช้งาน PHP Web Application ได้ครับ

ในขั้นตอนการลงมือทำ จำเป็นต้องมี Tools และ Skills ดังต่อไปนี้ครับ

  • Docker Community Edition เพราะฟรีครับ
  • Text Editor ตอนนี้แนะนำ VS Code นะครับ
  • Docker basic skill
  • Command line skill

คำสั่งทุกคำสั่ง ผมจะทำบน Terminal บนเครื่อง Mac และคำสั่งปลีกย่อยของ Docker จะขอไม่อธิบายมากนะครับ

สำหรับใครที่ไม่เคยใช้ Docker มาก่อน แนะนำให้ลองหาอ่านพวกคำสั่งต่างๆ ดูคร่าวๆ ก่อนนะครับ

ตรวจสอบ Docker

เราเริ่มกันที่ตรวจสอบก่อนนะครับว่าเครื่องเราใช้ Docker ได้แน่ๆ ด้วยคำสั่ง

docker -v

ถ้าเครื่องเรามี Docker พร้อมใช้งาน ก็น่าจะแสดง Docker Version ที่ติดตั้งอยู่บนเครื่องเราออกมาครับ

Pull PHP image มาใช้

ในขั้นตอนนี้ให้ใช้คำสั่ง

docker pull php:7.2-apache

ระหว่างนี้นับ 1 ถึง 1,000,000 รอไปก่อนนะครับ

ที่เลือกใช้ Image ตัวนี้ เนื่องจากว่า ทาง PHP เค้ารวม Apache HTTP มาให้แล้วครับ เราไม่ต้องเสียเวลามาทำ Web Server เอง

Run Container

หลังจากที่เรา Pull Image มาแล้ว เรามาลอง สร้าง Container ขึ้นมาจาก Image กันครับ ด้วยคำสั่ง

docker run -p 80:80 --name hello-web01 php:7.2-apache

ตรงนี้ให้ระวังเรื่อง Port ด้วยนะครับ ถ้าเครื่องเรามี Application อื่นที่ใช้ Port 80 อยู่ให้เปลี่ยนไปใช้ Port อื่นแทนนะครับ เช่น

docker run -p 8081:80 --name hello-world01 php7.2-apache

ถ้าคำสั่งทำงานสำเร็จ ผลที่ได้ควรจะออกมาในลักษณะตามรูปครับ จากนั้นให้เราลอง เปิด Web browser นะครับ ใส่ localhost นะครับ

อ่ะ ตอนนี้ตอนนี้มี Web server ทำงานแล้ว เพียงแต่ยังไม่มี ไฟล์ PHP อะไรให้ทำงานครับ มันเลยแสดงผลมาแบบนี้

เริ่มต้นที่ phpinfo()

ขั้นตอนนี้ให้สร้างไฟล์ info.php ขึ้นมาก่อนนะครับ

จากนั้น ใช้คำสั่ง

docker run -p 80:80 -v "$PWD"/src:/var/www/html --name hello-web02 php:7.2-apache

ตรงนี้จะต้องระวังเรื่อง Path หน่อยนะครับ ถ้าคำสั่งทำงานสำเร็จ ลองเปิด Web browser นะครับ ใส่ localhost/info.php ผลที่ได้ควรจะออกมาในลักษณะตามรูปครับ

ตอนนี้ไฟล์ info.php ที่เราทำไว้ ก็สามารถใช้งานได้แล้วครับ

ขั้นต่อมาให้เราลอง สร้างไฟล์เพิ่มขึ้นมาอีก 1 ไฟล์ครับ เอาเป็น hello.php นะครับ

ลองเปิด Web browser นะครับ ใส่ localhost/hello.php ผลที่ได้ควรจะออกมาในลักษณะตามรูปครับ

มาถึงตรงนี้เราก็สามารถ Dev PHP Web Application บนเครื่องเราได้ โดยไม่ต้องพึ่ง XAMPP, MAMP หรือ App serv อีกแล้วครับ

แต่… ชีวิตไม่เคยง่าย

ถ้าเราลอง Find mysqli จาก phpinfo() เราจะพบว่า ไม่มี …

อ้าว แล้วถ้า Application ของเราต้องต่อกับ Database จะทำอย่างไรล่ะ

เราก็ต้อง Modify PHP image นิดหน่อยครับ โดยการเปิดใช้งาน mysqli extension ครับ

โดยเราต้อง สร้างไฟล์ Dockerfile ขึ้นมาครับ หน้าตาประมาณนี้ครับ

จากนั้นใช้คำสั่ง

docker build -t docker101 .

การใช้คำสั่งนี้จะต้องระวังเรื่อง Path ด้วยนะครับ

ระหว่างนี้ก็นับเลข 1 ถึง 1,000,000 รอจนกว่าจะเสร็จครับ ถ้าไม่มีปัญหาอะไร ให้ใช้คำสั่ง

docker images

ผลที่ได้ควรจะออกมาในลักษณะตามรูปครับ

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

ขั้นต่อไป คือการสร้าง Container ขึ้นมาจาก Image ที่เราสร้างขึ้นมา ด้วยคำสั่ง

docker run -p 80:80 -v "$PWD"/src:/var/www/html --name hello-web03 docker101:latest

จากนั้นลองตรวจจาก phpinfo() ลองหา mysqli คราวนี้จะเจอแน่นอนครับ

มาถึงขั้นนี้ เราจะสามารถ Dev PHP Web Application บนเครื่องเราได้ค่อนข้างจะสมบูรณ์แล้วครับ หากต้องใช้งาน extension ตัวอื่น ก็ต้องไปแก้ไฟล์ Dockerfile เพิ่มเติมนะครับ

Dev เสร็จแล้ว อยาก Deploy ทำอย่างไร

สำหรับขั้นตอนก่อนหน้านี้ มันจะเหมาะกับระดับการ Dev บนเครื่องตัวเองเท่านั้นนะครับ ไม่เหมาะกับการเอาไปใช้งานบน Production ครับ

การเอาไปใช้งานบน Production เราควรจะรวม Code เข้าไปใน Image ด้วยครับ เพื่อตอนที่เอาไป Deploy เราจะได้สั่งแค่ประมาณ docker run docker101:latest บนเครื่อง Production แล้วก็ใช้งานได้เลย

รวม Code เข้าไปใน Docker Image

เราจะต้องไปแก้ Dockerfile ครับ โดยเพิ่มคำสั่ง COPY เข้าไปครับ

แล้วก็สั่ง Build Docker Image อีกครั้ง ด้วยคำสั่ง

docker build -t docker101 .

การใช้คำสั่งนี้จะต้องระวังเรื่อง Path ด้วยนะครับ ผลจาก Teminal ควรจะมีหน้าตาลักษณะนี้นะครับ

จากนั้น ให้สร้าง Container ขึ้นมาจาก Image ที่เราสร้างขึ้นมา ด้วยคำสั่ง

docker run -p 80:80 --name hello-web04 docker101:latest

จะเห็นว่าคำสั่ง docker run ครั้งนี้ เราจะไม่ Mount code ของเราเข้าไปแล้วนะครับ เนื่องจาก ใน Dockerfile เราได้สั่งให้ Copy code เข้าไปใน Image แล้ว เมื่อเอา Image มาสร้าง Container จึงมี Code ติดมาด้วยครับ

ในการใช้งานจริง Project ของเรา อาจจะต้องใช้ของบางอย่างจาก Composer ฉะนั้น เราสามารถ เอาคำสั่ง composer install ไปวางไว้ใน Dockerfile ได้เหมือนกันครับ

ก็จบเนื้อหาของการนำ Docker มาใช้งานแทน WAMP, XAMPP หรือ App serv แล้วนะครับ หวังว่า Blog นี้ น่าจะเป็นประโยชน์กับหลายๆ คน โดยเฉพาะคนที่เป็น PHP Dev แล้วเจอปัญหาในลักษณะข้างต้น ต่อไปเราจะไม่บ่นเรื่องปัญหาข้างต้นกันแล้ว แล้วไปบ่นกับปัญหาอื่นๆ (เช่น ใช้ Docker บน Production ไม่ได้ 😢)

สวัสดีครับ

Thanks to Antony Harfield

--

--