ต่อกันกับตอนที่ 3 ตอนนี้คงไม่ได้ยาวมาก จะพูดถึงเรื่อง "การวาง Server Stack ด้วย Docker" ขอรับ ก็คือการติดตั้ง nginx, PHP7FPM, MySQL Server และแอปอื่นๆที่เกี่ยวข้องบน Server โดยวางไว้บน Docker อีกที ถามว่าทำไมต้องใช้ Docker ด้วย? มันคืออะไร? มันมีประโยชน์ยังไง? มันใช้ยากมั้ย? อ่ะ มาอ่านกัน
อะไรคือ Docker?
จริงๆงานการใช้ Docker เป็นงานของ System Admin ไม่ใช่งานของ Web Developer มันจะเป็นส่วนของ "การติดตั้งแอปต่างๆใน Stack และเชื่อมโยงเข้าด้วยกันจนใช้งานได้"
ซึ่งถ้าพูดถึงการติดตั้งแอปแล้ว หากใครได้ทำงานด้านนี้ก็จะรู้ว่าเวลาติดตั้งแอปมันวุ่นวายมากกก เช่น จะลง nginx ก็ต้องติดตั้งแบบโน้นแบบนี้ จะลง MySQL ก็ต้องพิมพ์โน่นพิมพ์นี่ยาวเหยียด จะทำให้ PHP สามารถเชื่อมกับ MySQL ได้ก็ต้องติดตั้ง Extension มากมาย
หนำซ้ำ การติดตั้งบางอย่างต้องอาศัยการคอมไพล์จากซอร์สโค้ดซึ่งกินเวลานานมากอีกด้วย นี่ไม่นับรวมปัญหาที่อาจเกิดจากการที่ Compiler หรือไลบรารี่ไม่สมบูรณ์ซึ่งเกิดขึ้นได้เสมออีก
สรุปกว่าจะได้ LEMP Stack ธรรมดาๆต้องใช้เวลาติดตั้งกันเป็นชั่วโมง หรือถ้าเป็นคนเริ่มต้นใหม่ก็อาจจะเป็นวันๆ ถ้าเกิด Server เดี้ยงทีแล้วต้องลง Server ใหม่นี่ถึงกับกรีดร้องกันเลยทีเดียว
ปัญหายังไม่หมดแค่นั้น อนาคตหากมีความจำเป็นต้องเปลี่ยน OS ของ Server เช่น เปลี่ยนจาก Ubuntu 14.04 LTS เป็น Ubuntu 16.04 LTS เวอร์ชันของแอปที่เราจะลงได้ก็ต่างกัน ก็ต้องศึกษาการติดตั้งแอปใหม่หมด เมื่อแอปเปลี่ยนเวอร์ชันก็ต้องมาศึกษาการ Config ใหม่หมดอีก
ปัญหาอื่นก็มีอีก เช่น เครื่อง Development ลงแอปไว้เวอร์ชันนึง แต่บนเครื่อง Production ลงไว้อีกเวอร์ชันนึง สมมติเป็น PHP ละกัน ผลคือตอนทดสอบบนเครื่อง Development ใช้งานได้ทุกประการ แต่พอเอาขึ้น Production ปุ๊บ พัง ! เพราะ PHP พอเป็นคนละเวอร์ชันก็อาจจะทำให้โค้ดบางส่วนทำงานไม่ได้นั่นเอง
หรือถ้าเป็น nginx เรา Config บนเครื่อง Development ไว้อย่างดี พอขึ้นเครื่อง Production ปรากฏว่าเป็นคนละเวอร์ชันกันซะอย่างงั้น ก็ทำไงหละ ... Config ใหม่อีกรอบ สรุปคือต้องทำสองครั้ง หากมีการแก้ไขก็ต้องแก้ไขสองที่ (เครื่อง Dev และเครื่อง Production)
อันนี้เป็นแค่ปัญหาเบื้องต้น แต่ก็ถือเป็นปัญหาใหญ่ที่ทุกคนเจอมานานเป็นสิบปี สรุปปัญหาใหญ่ๆแบบอ่านง่ายๆได้สามข้อ
- กว่าจะตั้ง Server ใหม่ขึ้นมาได้เครื่องนึงมันใช้เวลาเยอะมาก
- เปลี่ยน OS (เช่นจาก Ubuntu เป็น Fedora) ก็ต้องหาวิธีติดตั้งใหม่
- ความไม่เหมือนกันของเครื่อง Development และเครื่อง Production ทำให้ต้องทำงานซ้ำซ้อนและเกิดปัญหาขึ้นได้ง่ายมากตอน Deploy
จริงๆปัญหาอื่นก็มีอีก แต่ที่ลิสต์มาน่าจะใหญ่และเจอบ่อยสุด
แต่ก่อนมันก็ยังไม่ใช่ปัญหามากหรอกเพราะเราไม่ได้ตั้ง Server ใหม่กันบ่อยๆ ตั้งทีเดียวก็จบแล้วใช้งานยาวๆ แต่ในยุคของ Cloud อย่างทุกวันนี้ การเพิ่มลด Server ตาม Demand กลายเป็นเรื่องปกติมาก วันดีคืนดีต้องเพิ่ม Server ขึ้นมา วันดีคืนดีต้องลด Server ลง ถ้างั้นการติดตั้งแอปต่างๆต้องเป็นไปอย่างรวดเร็ว กดปุ๊บขึ้นปั๊บและต้องไม่มีปัญหาเป็นอันขาด อันนี้สำคัญมากๆ ไม่งั้นไม่ได้นอนกันอ่ะ
เราจะทำยังไงดีถ้าให้การติดตั้งแอปต่างๆบน Server มันง่ายขึ้น แบบสร้างเครื่องที่ลง OS เปล่าๆมาปุ๊บก็ติดตั้งแอปต่างๆเพิ่มปั๊บจนใช้งานได้แล้วก็รันเลย
งั้นเอางี้ ... สร้าง Shell Script ติดตั้งแอปเลยละกัน แบบว่ากด Enter ทีเดียวมันติดตั้งทุกแอปมาให้เลย
ก็พอได้นะ แต่เดี๋ยวก่อน ! ตะกี้เราบอกแล้วว่า Server บางทีมันก็อาจจะเป็นคนละ OS Version ได้ Script ดังกล่าวก็เลยกลายเป็นว่าอาจจะใช้งานได้บ้างไม่ได้บ้าง วันนี้ใช้ได้อนาคตอาจจะใช้ไม่ได้ หรือบางทีถ้าเรา Dev บน Ubuntu แต่ตอนรัน Production จริง Server ดันเป็น Fedora ก็เฮลไฮดร้าเลยนะ สคริปต์ทำอะไรไม่ได้เลย
สรุป Shell Script เป็นทางเลือกที่ไม่เสถียร ถ้าเราไม่มีอำนาจคุมฝั่ง Server แบบ 100% มันก็เอาไปใช้จริงไม่ได้
ถ้างั้นใช้วิธีนี้แทน ทำ Server ให้เป็น Standard เดียวกันเลยละกันโดยไม่สนว่า OS จะเป็นอะไรหรือเป็นเวอร์ชั่นไหน ... ทำยังไงหละ? เอาแบบง่ายๆก่อน "ติดตั้ง VM ซะะะ" ยกตัวอย่างเช่นลง Ubuntu 14.04 LTS ไว้บน VirtualBox แล้วค่อยติดตั้งแอปต่างๆบน VM นั้น คราวนี้ก็รัน Server Stack กันบน VM นั่นแหละ ส่วน Port ต่างๆก็ Bind จาก Host OS ไป Guest OS เลย เย้! ใช้งานได้ละ
ฟังๆดูก็โอเคนะ แต่ปัญหาใหญ่ๆของการติดตั้งแบบนี้คือเรื่องของ Performance เพราะการทำงานของ VM คือแอปต่างๆจะรันโค้ดบน Guest OS ด้วย Kernel ของตัวเอง แล้วตัว VM Engine ค่อยเอาการทำงานนั้นไปแปลงเป็นการทำงานของ Host OS อีกที สรุปแล้วมันคือการรันสองชั้น ทำให้ประสิทธิภาพแย่มากๆนั่นเอง แถมการมี OS นึงรันโดยสมบูรณ์แบบอยู่บนอีก OS นึงก็เป็นอะไรที่หนักมาก กินทรัพยากรต่างๆมากมาย กว่าจะ Start ขึ้นมาได้ก็ใช้เวลานานมาก
นี่เป็น Stack การทำงานของ VM
ถ้ามีหลายๆ VM รันอยู่บน Host OS ก็จะเป็นภาพแบบนี้
หนัก! ถ้ามี VM มากกว่านี้ก็หนักขึ้นไปอีกเป็นเท่าทวีคูณไปเรื่อยๆ
และนั่นเองเป็นจุดกำเนิดของ Docker (ลากยาวมาตั้งนาน)
ลองคิดดูว่าแอปแต่ละตัวมันต้องใช้อะไรบ้างในการรันขึ้นมา? จริงๆมันก็แค่ Binary กับ Library ป่ะ? ถูกกกก
และนั่นแหละครับ Docker มันคือความสามารถในการห่อ Binary/Library ของ OS และแอปที่เราต้องการพร้อมด้วยส่วนอื่นๆที่เราต้องการให้มันทำงาน เช่น Ubuntu + เว็บของเรา + nginx + php7fpm ห่อรวมกันไปแล้วเอาไปรันได้เลยโดยไม่ต้องผ่าน Guest OS (ก็มันครบแล้วหนิ) แต่จะไปรันบนสิ่งที่เรียกว่า Docker Engine ซึ่งขึ้นตรงกับ Kernel ของ Host OS แทน ซึ่งเจ้าก้อนที่ถูกห่อแล้วทำงานอยู่บน Docker Engine นี้เราจะเรียกมันว่า Docker Container ครับ (ศัพท์ระดับอนุบาลตัวแรกของโลก Docker)
สรุปแล้วการทำงานของ Docker ก็เลยเป็นแบบนี้
ซึ่งในวงที่เห็นอาจจะประกอบด้วย Lib ของ Ubuntu + NGINX + เว็บของเรา ซึ่งจะเห็นได้ว่ามันเพียงพอจะเอาไปรันที่ไหนก็ได้ที่เป็น Linux แล้ว มันมีครบทุกอย่างแล้ว ... นี่แหละครับ Container หละ อะไรจำเป็นต้องใช้ในการรันก็ยัดๆๆ
ผลคือ
1) แอปนั้นๆรันตรงกับ Host OS เลย ไม่ต้องผ่าน Guest OS ประสิทธิภาพเลยดีขึ้นมากๆอย่างมีนัยสำคัญ
2) Guest OS ไม่ได้ทำงานแบบเต็มสูบเหมือน VM ไม่กินทรัพยากรที่ไม่จำเป็นอีกต่อไป
3) Start เร็วมาก เพราะไม่มี Guest OS ทำงานนั่นเอง
4) เบามาก ทำงานเหมือนเป็น Process เดียวเพราะจริงๆมันก็รันแค่นั้น ต่อให้เพิ่มมาอีกเป็น 10 Containers ก็ไม่ได้หนักขึ้นแบบเว่อร์ๆ มันก็แค่ Process นึง
ความหล่อความเท่ยังไม่หมดแค่นั้น หากว่า Container แต่ละตัวมี Binary หรือ Library ที่เหมือนกันมันก็ยังฉลาดพอที่จะรวบให้สามารถ Share กันได้ด้วย อย่างในรูปด้านล่างนี้มี 4 Containers แต่มีบางส่วนที่สามารถแชร์กันได้มันก็แชร์กัน
นี่เองคือ Docker ครับ อยากจะรันแอปอะไรก็รันในรูปแบบ Container ได้เลยแล้วมันก็ทำงานได้ทันที ไม่ต้องลงอะไรให้วุ่นวาย แค่ลง Docker และสร้าง Container มา
ถึงตอนนี้เข้าใจระบบการทำงานของ Docker คร่าวๆแล้วหละ เอ๊ะ แล้วมันทำให้การติดตั้งแอปต่างๆเร็วขึ้นได้ยังไง?
คำตอบคือ ถ้า Container แบบไหนใช้บ่อยเราก็สามารถสร้างเป็นอิมเมจเก็บไว้ได้ครับ ซึ่งเราก็เรียกกันตามนั้นเลยว่า Docker Image (ศัพท์ระดับอนุบาลตัวที่สอง) อนาคตหากต้องการจะสร้าง Container แบบเดียวกันนี้ก็พิมพ์บรรทัดเดียวแล้วมันจะสร้างมาตั้งให้และใช้งานได้เลย
ยกตัวอย่างเช่นอยากได้ nginx ขึ้นมาทำงาน ไม่ต้องมา apt-get ไม่ต้องหา Installer ให้วุ่นวายละ แค่หา Docker Image ของ nginx ที่มีคนทำไว้แล้วหรือที่เคยสร้างเก็บเองไว้ก็ได้ แล้วกดบรรทัดเดียว มันก็จะเด้ง nginx ขึ้นมาในรูปแบบ Docker Container ให้ใช้งานได้เลย
ใช้เวลาเพียงไม่กี่วินาทีเท่านั้นเพราะมันเป็นแค่การก็อปปี้ไบนารี่มารัน ไม่ต้องคอมไพล์สดอะไรอีกต่อไปเพราะทุกอย่างที่เคยติดตั้งไว้มันอยู่ในรูปแบบของอิมเมจแล้ว ยกมาตั้งทำงานได้เลย และใช้งานได้แน่นอนเพราะว่าทุกอย่างมันรวมอยู่ในอิมเมจแล้ว อีกร้อยปีก็ไม่มีปัญหาแน่นอน
ผลพลอยได้
ผลพลอยได้แรกของการที่ Docker ออกแบบระบบมาแบบนี้คือ เราสามารถติดตั้งแอปได้หลายเวอร์ชันในเครื่องเดียว เช่นลง PHP7 และ PHP5.5 ได้ในเครื่องเดียวกันและแยกทำงานได้เลย เพราะมันอยู่ในคนละ Container นั่นเอง ถ้าเป็นแต่ก่อนถ้าจะอัปเดตจาก PHP5.5 เป็น PHP7 นี่หัวฟูเลยนะ แต่ด้วย Docker มันง่ายมาก บรรทัดเดียวก็มี PHP7 ใช้เลยแถม PHP5.5 ตัวเก่าก็ยังใช้งานได้อยู่อีกด้วย
ผลพลอยได้ที่สองคือ เราสามารถติดตั้งแอปที่ไม่ควรจะติดตั้งได้ได้ด้วย ยกตัวอย่างเช่นแอปบางตัวจำเป็นต้องรันบน Ubuntu 14.04 แต่เครื่องเราเป็น Ubuntu 16.04 จะทำยังไงดีหละ? ... ก็สร้าง Container ที่ภายในเป็น Ubuntu 14.04 ซะสิ แล้วค่อยติดตั้งแอปบน Ubuntu 14.04 ใน Container นั้นๆ จบ ติดตั้งได้แล้ว ใช้งานได้ด้วย !
สุดท้าย อันนี้สำคัญมาก ความสามารถในการควบคุมให้เครื่อง Development และ Production มี Environment เหมือนกันทุกประการ
บ่อยครั้งมากที่เราพัฒนาข้ามแพลตฟอร์มกัน เช่นเครื่อง Production เป็น Linux แต่เราไป Dev กันบน Windows ซึ่งข่าวดีคือ Docker สามารถใช้งานได้ทั้งบน Linux, Windows และ Mac OS X
ก่อนหน้านี้นี่ต้องทำกันยังไง เครื่อง Production ก็ติดตั้งกันไปตามวิธีของ Linux เครื่อง Development ก็ติดตั้งไปตามวิธีของ Windows และถามว่ามันเหมือนกันเป๊ะๆมั้ย? ตอบได้เลยว่า ไม่
ข้อจำกัดมันเยอะมาก แค่จะให้เวอร์ชันของแอปต่างๆใน Stack เหมือนกันทั้ง Linux และ Windows นี่ก็แทบเป็นไปไม่ได้แล้ว ผลคือเราทดสอบเว็บบนเครื่อง Development อย่างดิบดี ใช้งานได้สวยงาม แต่พอเอาขึ้น Production ... พังจ้าาา ต้องมานั่งแก้อะไรวุ่นวายอีกมากมายปวดหัว
แต่พอมี Docker มาปัญหานี้ก็ไม่ใช่ปัญหาอีกต่อไป เพราะเราสามารถดึง Docker Image ตัวเดียวกันมาสร้างเป็น Container แบบเดียวกันทุกประการมารันได้ทั้งบน Linux, Windows และ Mac OS X
ผลคือเราสามารถควบคุม Development Machine และ Production Machine ให้เหมือนกันทุกประการได้เลย ทดสอบบนเครื่อง Development ใช้งานได้ก็สบายใจได้ว่า Production ใช้งานได้แน่ๆ หากมีการเปลี่ยนแปลงอะไรใน Configuration ก็แก้ไขที่เดียวแล้วเอาขึ้น Production ได้เลย ทั้งสะดวกและปลอดภัยยั่งยืน
อย่างไรก็ตาม เนื่องจาก Docker ถูกสร้างมาโดยอิงกับ Kernel ของ Linux ทำให้มันไม่สามารถทำงานบน Windows และ Mac OS X ด้วยตัวมันเอง หากใช้งานบนอะไรที่ไม่ใช่ Linux เราจะต้องสร้างสิ่งที่เรียกว่า Docker Machine ขึ้นมาก่อน ซึ่งจริงๆมันก็เป็นอะไรที่เราๆคุ้นเคยกันอยู่แล้วแหละเพราะมันก็เป็นแค่ VM ของ Linux บน VirtualBox นั่นเอง
พวก Docker Container ต่างๆจะทำงานบน VM ของ Linux อีกทีนึงบน Windows และ Mac OS X
แต่ก็ไม่ใช่ปัญหาอะไร ไม่ได้กินทรัพยากรเครื่องมากเพราะ Docker Machine ตัดส่วนที่ไม่จำเป็นทิ้งไปหมด เลยค่อนข้างเบา ที่กินหนักๆก็คงเป็นแรมที่กินไปเลย 1GB แต่ถ้าเป็น Developer ก็คงเคยชินกับการซื้อแรมมาถวายซอฟต์แวร์อยู่แล้วมั้ง
สำหรับตัวที่ทำงานโดยตรงบน Windows และ Mac OS X โดยไม่ต้องผ่าน VM กำลังจะออก แต่ไปอ่านดูแล้วก็มีข้อจำกัดพอสมควร เช่น Windows ต้องเปิด Hyper-V ดังนั้นก็รอดูกันไปว่าสุดท้ายจะใช้ท่าไหนดี
อย่างไรก็ตามจากประสบการณ์ที่ใช้ การใช้ผ่าน Docker Machine ก็ไม่ได้แย่อะไร ไม่โหลดเครื่องและเร็วดีปกติเลย =)
ทำไมถึงใช้ Docker ในโปรเจคนี้?
เหตุผลหลักคือ ต้องการคุม Environment ให้เป็นมาตรฐานเดียว ในกรณีที่ต้องการเพิ่ม Server ก็จะต้องกดทีเดียวแล้วสเกลได้ทันที ไม่ใช่มาลงอะไรให้วุ่นวายอีกต่อไป (กดทีเดียวได้จริงๆนะ เขียนสคริปต์ไว้ รอไม่กี่นาทีก็เสียบเข้า Load Balance ได้เลย)
อีกเหตุผลนึงคือ ถ้ามีเหตุจำเป็นต้องย้าย Server ไปอยู่ที่อื่น ต้องทำได้ในเวลาไม่กี่นาที ซึ่ง Docker ทำให้สิ่งนี้เป็นไปได้นั่นเอง จะยกไปตั้งที่ไหนก็ได้
เหตุผลสุดท้ายคือ ... ขี้เกียจลงแอปครับ ... กดทีเดียวแล้วมันได้แอปมาใช้เลยแล้วจะลงให้วุ่นวายทำไม คือมันไม่ได้สร้างมาเพื่อคนขยันนะ มันสร้างมาเพื่อคนขี้เกียจ เนยนี่แหละ ~.~
โครงสร้าง Docker Container ที่ใช้ในโปรเจคนี้
เนื่องจากว่าตั้งใจจะใช้บริการฟรีของที่ต่างๆ ก็เลยออกแบบ Docker Container ให้สามารถเอาสิ่งที่สร้างไปวางไว้ที่ต่างๆได้โดยไม่มีข้อมูลส่วนตัวหลุดรอดออกไป สุดท้ายเลยออกแบบให้
- ยัดซอฟต์แวร์ต่างๆไว้ใน Docker Image โดยไม่มี Config หรือโค้ดใดๆที่เกี่ยวข้องกับระบบที่ทำไว้ในนั้น จากนั้นก็เอาขึ้น Docker Hub ซึ่งเป็นเว็บสำหรับเก็บ Docker Image เก็บไว้ (ฟรี)
- พวก Config ต่างๆของแต่ละอิมเมจเอาขึ้น Git รวมไว้
- ใช้ Docker Compose ช่วยให้การสร้าง Docker Container ง่ายขึ้น และสร้าง docker-compose.yml
ไว้รวมกับ Git ด้านบนให้สามารถ Launch Docker Container ได้เลยด้วยบรรทัดเดียว โดยแน่นอน เลือกเอา Git ที่ทำมานี้ขึ้นที่ bitbucket ครับ ฟรีหนิ
- ตัวโค้ดของเว็บก็เอาขึ้น Git เข้า bitbucket เช่นกัน โดยทำเป็น submodule ของ Git ด้านบนอีกที
สำหรับ Config และโค้ดของเว็บที่ถูกแยกออกมานั้นจะถูกเชื่อมกลับเข้าไปใน Docker Container ผ่านท่า Volume นั่นเอง (สำหรับคนที่ยังไม่รู้จัก มันคือการ Map ไฟล์หรือโฟลเดอร์ภายใน Container เข้ากับไฟล์ข้างนอก ผลคือจะใช้ไฟล์ข้างนอกที่ Map เข้าไปแทนไฟล์ที่อยู่ใน Container หากมีการแก้ไขอะไรที่ไฟล์ข้างนอกก็จะกระทบต่อข้างในด้วยนั่นเอง)
โปรเจคนี้ทำ Server ไว้สามส่วน ส่วนแรกคือ ส่วนของเว็บ ก็ทำ Container ไว้ 4 อัน nginx, PHP7FPM, memcached และ MySQL Server แล้วให้แต่ละตัวคุยกันผ่าน Network Bridge ซึ่งเป็นระบบการสื่อสารระหว่าง Docker Container ของ Docker เอง
แล้วก็ Bind เฉพาะ Port 80 กับ 443 เข้ากับก้อน Container ของ nginx ที่เหลือปิดไว้ไม่ให้ติดต่อจากภายนอกได้ คราวนี้ตอนกดเข้าเว็บผ่าน Port 80 หรือ 443 ก็จะไปเรียก nginx ใน Container ที่วางไว้ จากนั้น nginx ก็จะติดต่อไปยัง Container อื่นๆตาม Rule ที่เขียนไว้ใน Configuration ผ่านทาง Network Bridge ที่เชื่อมแต่ละ Container ไว้ด้วยกัน (Docker Compose มันสร้างขึ้นมาให้โดยอัตโนมัติ ไม่มีอะไรพิเศษ)
ซึ่ง Container แต่ละตัวเราสร้าง Docker Image ของตัวเองไว้เพราะมีการปรับเปลี่ยนโน่นนี่นิดหน่อยให้เหมาะกับการใช้งานของเราและอีกอย่างคือส่วนตัวไม่ค่อยไว้ใจคนอื่นเลยไม่กล้าใช้อิมเมจที่คนอื่นทำมาเท่าไหร่ ทำเองดีกว่าสบายใจสุด
โดยตอนนี้ทั้งสี่ก้อนรันอยู่บนเครื่องเดียวกันเพราะยังอยากจะควบคุมค่าใช้จ่ายอยู่ แต่อนาคตถ้าพร้อมจะสเกลแล้วก็จะแยก MySQL Server ออกไปเป็นอีกเครื่อง ซึ่งไม่ใช่ปัญหาเพราะระบบออกแบบเผื่อไว้แล้ว สามารถแยกเป็น Server ใหม่ได้ในเวลาไม่กี่นาที
แล้วถามว่าจริงๆเรายัด nginx, PHP7FPM และ memcached เข้าไปใน Container เดียวเลยได้มั้ย?
จริงๆทำได้นะ แต่ทำไมเราถึงแยก? สาเหตุหลักๆเพราะเราอยากให้มันเป็นโมดูล 1 Container ควรทำงานงานเดียวเพื่อที่จะได้คล่องตัว อนาคตหากต้องการเปลี่ยน PHP7FPM ไปใช้ HHVM ก็จะได้สามารถทำได้โดยไม่ต้องไปยุ่งกับ nginx เป็นต้น จริงๆมันก็เหมือนกับการเขียนโค้ดเลยนะ มันคือเรื่องของ Modularity
อันนี้ก็แล้วแต่แนวทาง แต่สำหรับเราเราชอบแนวทางนี้ แยกทุกอย่างออกมาเป็นชิ้นย่อยที่สุดแล้วค่อยให้แต่ละอันมาทำงานร่วมกัน
ส่วนที่สองคือส่วนของ Video Streaming Server อันนี้ก็ไม่ต่างกันมาก แนวทางเดียวกันเป๊ะ
ส่วนสุดท้ายเป็นการจำลอง S3 ไว้ใน Server ตัวเอง สาเหตุคือเรื่องของ Scalable พวกรูปต่างๆไม่ควรจะถูกอัปโหลดไปเก็บไว้ในสองส่วนด้านบนเพราะจะทำให้สเกลออกไม่ได้ เราก็เลยสร้างเป็น Cloud Storage จำลองมาอีกหนึ่งก้อนเพื่อเก็บไฟล์อย่างเดียว สำหรับ Stack ตัวนี้ก็ทำเป็น Docker เช่นกัน แต่คงไม่พูดถึงโครงสร้างนะ มันก็โค้ดอัปโหลดและจัดการไฟล์ธรรมดาๆแหละ ไม่ได้เอา Open Stack อะไรมาตั้ง
สุดท้ายโครงสร้างโดยรวมฝั่ง Web Server เลยออกมาแบบนี้
โดยส่วนของ MySQL Server เป็นภาพหลังจากแยกแล้ว ซึ่งตอนนี้ยังไม่ได้แยก Server อ่านะ ส่วน Load Balancer ทำเตรียมไว้แล้วแต่ว่ายังไม่ได้เอามารันเฉยๆเพราะยังมีแค่เครื่องเดียว สังเกตดูว่าถึงจะยังไม่ได้รันตามที่ออกแบบแต่ก็สามารถสลับไปเป็นแบบเต็มรูปแบบได้ภายในเวลาไม่กี่นาที เพราะโค้ดและ Infra ออกแบบมาให้สเกลได้นั่นเอง
เรายังไม่จำเป็นต้องสเกลตั้งแต่ตอนแรก แต่การออกแบบโค้ดและ Infra ควรจะวางให้สามารถสเกลได้ตั้งแต่แรก
ส่วนของ Video Streaming Server ก็แยกออกไปเป็นอีกระบบนึง แต่ก็ไม่มีอะไรมาก คล้ายๆกัน
และผลของการใช้ Docker ในงานนี้คือ
1) สามารถทำ Server Stack ทั้งอันบนเครื่อง Development ได้เลย ต้องการปรับเปลี่ยนอะไรก็ปรับเปลี่ยนกันในเครื่อง Development สร้างเป็น Docker Image เก็บไว้ใน Docker Hub พอจะใช้งานจริงก็แค่ดึงอิมเมจไปอัปเดตบน Production บรรทัดเดียวจบ ไม่ต้อง ssh แล้วพิมพ์โน่นพิมพ์นี่ยาวเหยียดให้วุ่นวายอีกต่อไป มันเป็นอะไรที่สบายมากจริงๆ สบายทั้งใจและกาย
2) สามารถเปลี่ยนเครื่องพัฒนาได้อย่างคล่องตัว บางวันก็นั่งทำบน Windows บางวันก็นั่งทำบน Mac OS X ไม่มีปัญหาและความกังวลใจอีกเลย ทุกอย่างอยู่บน Docker Hub และ Bitbucket แล้ว และทุก Environment ก็สามารถควบคุมได้ จะทำบนแพลตฟอร์มไหนก็ได้ผลเหมือนกันหมดและตอนเอาขึ้น Production ก็ไม่มีปัญหาใดๆ
3) การที่เราสามารถ Map Volume ออกมายัง Filesystem ของ Host OS ได้ทำให้เราสามารถแก้ไขโค้ดแล้วเห็นผลได้ทันที ดังนั้นเราสามารถใช้ Docker ในงาน Development ได้อย่างไม่มีปัญหาและยังสะดวกมากอีกด้วยครับ
4) สามารถสเกลได้ ถ้า Server ไม่พอก็สร้าง Server ใหม่และยกอิมเมจมาตั้ง Container ใหม่และเสียบเข้า Load Balancer ได้ทันที
5) จากด้านบนก็จะเห็นว่า ... พอทุกอย่างออกแบบมาในรูปแบบของ Docker Container เราก็เลยสามารถยกมันไปตั้งที่ไหนก็ได้อย่างง่ายดาย จริงๆตอนนี้เราสามารถขึ้น Server ใหม่แล้วกด Enter ทีเดียวแล้วมันจะกลายเป็นระบบ Online Learning System ตัวใหม่ได้ภายใน 2-3 นาทีเลย ข้อดีของ Docker เค้าหละ สะดวกมาก
สุขกายสบายใจ ไม่ต้องแปลกใจทำไม Docker ถึง Valuation ทะลุ 1 พันล้านเหรียญสหรัฐฯไปแล้ว และนี่ก็ไม่น่าจะเป็นยูนิคอร์นเขาหักด้วย ทุกอย่างดีมากอย่างชัดเจนและยังเติบโตขึ้นเรื่อยๆด้วย =)
ความรู้ที่ควรต้องมีก่อนมาใช้ Docker
ตอนนี้ใน Community จะคลั่ง Docker มาก แต่เกิน 90% พอไปดูว่า Docker คืออะไรแล้วก็เศร้าหมองสับสนงงงวยแล้วก็เลิกราไปในที่สุด สาเหตุเพราะหลายๆคนศึกษาผิดวิธีครับ
เราเชื่อในการศึกษาต่อยอด เชื่อเรื่องพื้นฐาน ถ้าจะรู้เรื่องนึงได้ควรต้องรู้เรื่องนึงมาก่อนงี้
สำหรับ Docker เราแนะนำว่าก่อนจะเริ่มใช้ ทุกคนควรมีพื้นฐานในการติดตั้ง Stack เองบน Linux โดยไม่ต้องใช้เครื่องมือพิเศษ ก็คือติดตั้งดิบเลย nginx ลงยังไง PHP7FPM ติดตั้งยังไง MySQL Server ติดตั้งยังไง
จากนั้นก็ลอง Config และเขียนเว็บเพื่อเอาไปรันบนนั้นให้ได้ก่อน แล้วก็ดู Performance ว่ามันกิน CPU เป็นยังไงบ้าง กิน I/O เป็นยังไงบ้าง
พอทำพวกนี้เป็นอย่างเข้าใจแล้วค่อยย้ายของที่ติดตั้งนี้ไปไว้บน Docker อีกทีนึง
สรุปคือติดตั้งจริงรันจริงให้เห็นจริงว่าพวกแอปต่างๆมันติดตั้งยังไงและทำงานร่วมกันยังไง นี่คือพื้นฐานของการไปต่อเรื่อง Docker ครับ ทำเป็นแล้วค่อยย้ายมาศึกษาเรื่อง Docker ต่อ
ส่วนตัวไม่อยากให้ข้ามขั้นมา Docker เลยเพราะคุณจะงงและเก่งขึ้นไม่ได้เลย ค่อยๆศึกษาทีละเรื่องนะ เอาพื้นฐานก่อน ไม่ใช่แค่ทำเว็บเป็นแล้วข้ามไป Docker เลย เพราะจริงๆแล้ว งาน Docker มันคืองานของ System Admin คนละสายกับ Web Programmer เลย ถ้าอยากจะเล่น Docker ก็ต้องเริ่มจากงานพื้นฐานด้าน System Admin ครับ
สรุป
ตอนแรกตั้งใจจะเล่าให้ฟังเฉยๆว่าเราตั้ง Docker ไว้ยังไง แต่ไปๆมาๆเพื่อให้เป็นประโยชน์สูงสุดเราเลยใช้ตัวอย่างจริงนี้อธิบายสำหรับคนไม่รู้จัก Docker ไปเลยละกันว่ามันคืออะไรและทำงานยังไงแบบคร่าวๆ ถึงจะยังไม่ได้ลงรายละเอียดแต่ก็หวังว่าจะเห็นภาพกันมากขึ้นครับ
ก็ยังไม่ได้ลงดีเทลมากเพราะ Docker ถ้าจะเห็นภาพจริงๆต้องพาลงมือทำ ไว้มีโอกาสจะทำเป็นวีดีโอสอนละกันโนะ บล็อกนี้เหมือนบทที่ 0 ให้เห็นภาพรวมและละลายความกลัวต่อสิ่งที่เรียกว่า Docker ให้ และถ้าเห็นภาพรวมแล้วระหว่างนี้ก็อยากให้ลองเล่นเลยครับ ลงมือทำเท่านั้นที่ครองโลก ทุกวันนี้ความรู้มีอยู่ทั่วไปในอินเทอร์เนต เราเป็น Dev เราต้องศึกษาด้วยตัวเองเป็น =)
กระซิบบอกก่อนละกันว่า "ใครบอกว่า Docker ยาก อย่าไปเชื่อ จริงๆมันง่ายมากกกก" ใครกลัวมันก็อย่าไปกลัวครับ มันง่ายจริงๆนะ
สำหรับผู้ที่ทำงานด้านสายเว็บผมไม่อยากให้หยุดแค่การทำเว็บ Backend/Frontend นะ ทุกคนควรจะสามารถวาง Stack ของ Server เองเป็นด้วย ส่วนตัวว่าคนสายทำงานบนฝั่ง Server ทุกคนควรทำเป็นจริงๆ เพราะถ้าเข้าใจการติดตั้ง Stack พวกนี้มันจะสอดคล้องกับแนวทางโค้ดที่เขียนออกมาด้วย และการติดตั้ง Server Stack นี่ก็ไม่ใช่พวกติดตั้ง XAMPP แล้วจบด้วย ควรจะทำแบบดิบๆคือติดตั้งเองทีละตัว และถ้าเป็นไปได้ก็อยากให้ตั้ง Server บน Linux ให้เป็น มันสำคัญและต่อยอดไปในอนาคตได้มากมายครับ
และถ้าติดตั้ง Server เป็นแล้วก็อย่าลืมมาลองจับ Docker ด้วย
อนาคตสาย Server มาทาง Container แน่นอน
คอยจับตาดูได้ครับ แบรนด์ต่างๆจะทยอยปั้น Container ของตัวเองออกมามากมาย และถ้าคุณเป็นอันนึงแล้วที่เหลือคุณก็จะเป็นเอง ถือเป็นประตูอีกบานนึงที่ทุกคนในสายนี้ควรก้าวผ่านครับ
จบ ... ตอนแรกว่าจะเขียนสั้นๆ ทำไมยาวฟระ ...