วิศวกรรม frontend สมัยใหม่ไม่เหมือนกับเมื่อทศวรรษที่แล้วเลย คุณไม่ได้แค่เขียน HTML และ CSS อีกต่อไป โปรเจกต์ทั่วไปในปัจจุบันมาพร้อมกับ Node.js runtime ที่เฉพาะเจาะจง, เวอร์ชันของ package manager ที่ถูกล็อกไว้, ชุดเครื่องมือ build ที่ซับซ้อน และ deployment pipelines ที่คาดหวังว่าทุกอย่างจะต้องสอดคล้องกันอย่างสมบูรณ์แบบ ระหว่างการ npm install ครั้งแรกไปจนถึงการ build เพื่อใช้งานจริง (production build) มักจะมีจุดแตกต่างเล็กๆ น้อยๆ แทรกเข้ามาเสมอ เพื่อนร่วมทีมใช้ Node 20 แต่คุณใช้ Node 18 เครื่องมือ CLI แบบ global บนเครื่องของคุณอาจจะช่วยปกปิดการขาดหายไปของ dependency บนเครื่องของพวกเขา แล้วประโยคที่ไม่มีใครอยากได้ยินก็ตามมา: "It works on my machine."
Docker ได้รับการยอมรับให้เป็นส่วนหนึ่งของเครื่องมือสำหรับ frontend เพราะมันช่วยขจัดความไม่แน่นอนเหล่านั้น มันจะรวมแอปพลิเคชันของคุณเข้ากับ runtime, system libraries และ dependencies ที่จำเป็นต้องใช้ไว้อย่างแม่นยำ ไม่ว่าคุณจะเขียนโค้ดบน Windows, ส่งงานจาก macOS หรือ deploy ไปยัง Linux cloud instance พฤติกรรมการทำงานของแอปก็จะยังคงเหมือนเดิมทุกประการ
ทำไม Frontend Developers ถึงควรให้ความสำคัญ
ปัญหาที่ Docker เข้ามาแก้ไขนั้นไม่ใช่เรื่องนามธรรม แต่มันเกิดขึ้นจริงในทุกๆ sprint
ความขัดแย้งของเวอร์ชัน (Version conflicts) ทำให้เสียเวลา โปรเจกต์ลูกค้าเก่าต้องการ Node 18, โปรเจกต์เสริมของคุณต้องการ Node 20 และงานสตาร์ทอัพใหม่ต้องการ Node 22 หากไม่มี container คุณต้องจัดการเรื่องนี้ผ่าน version managers ซึ่งมันก็ใช้ได้จนกระทั่งมันเริ่มมีปัญหา ความไม่สอดคล้องกันเพียงเล็กน้อยของเวอร์ชัน npm อาจเปลี่ยนวิธีการ resolve peer dependencies ส่งผลให้ build พัง ทั้งที่ในเครื่องคนอื่นกลับใช้งานได้ปกติ เมื่อ framework ประกาศเวอร์ชันใหม่ วงจรการทำงาน (feedback loop) ไม่ควรเป็นการเสียเวลาสองชั่วโมงไปกับการติดตั้งใหม่ แต่มันควรจะเป็นเพียงการเปลี่ยนไฟล์เดียวและการ restart container เท่านั้น
Global packages เป็นอีกหนึ่งสาเหตุของปัญหาที่เกิดขึ้นเงียบๆ คุณอาจจะมี Angular CLI, Expo หรือ Prisma ติดตั้งแบบ global ไว้ตั้งแต่เมื่อหกเดือนก่อน ในขณะที่นักพัฒนาคนใหม่ติดตั้งเครื่องมือเดียวกันแบบใหม่เอี่ยมและได้เวอร์ชันที่ต่างออกไป ทันใดนั้น build scripts ของคุณก็อาจจะแจ้งเตือน (warnings) ในแบบที่ไม่เคยเกิดขึ้นที่ไหนมาก่อน Docker แก้ปัญหานี้โดยการทำให้ทุกอย่างอยู่แค่ภายในโปรเจกต์ (project-local) คุณกำหนดเวอร์ชันของ Node ใน Dockerfile ของคุณ Dependencies จะถูกติดตั้งภายใน container ซึ่งแยกขาดจาก Operating System ของเครื่องหลัก (host) ไม่ว่าแล็ปท็อปของคุณจะเป็น macOS, Windows หรือ Ubuntu แอปพลิเคชันก็จะมองเห็นสภาพแวดล้อมที่เหมือนกันทุกครั้ง
ประโยชน์ในด้านการ Onboarding ก็เป็นเรื่องที่มองข้ามไม่ได้ พนักงานใหม่ไม่จำเป็นต้องอ่านไฟล์ readme ยาวสามหน้าเกี่ยวกับการติดตั้ง Homebrew, การตั้งค่า nvm aliases และการแก้ไขเรื่อง global permission พวกเขาแค่ติดตั้ง Docker, clone repository และรันคำสั่งเพียงคำสั่งเดียว การตั้งค่าที่เคยใช้เวลาทั้งบ่ายก็ลดเหลือเพียงไม่กี่นาที และเมื่อพวกเขาเปลี่ยนโปรเจกต์ ก็จะไม่มีอะไรค้างคา ไม่มีเครื่องมือ global ที่ไม่ได้ใช้งานทิ้งไว้ ไม่มี version managers ที่แย่งกันกำหนดลำดับความสำคัญใน PATH เครื่องของพวกเขาจะยังคงสะอาดอยู่เสมอ
Images และ Containers: พื้นฐานเบื้องต้น
หาก Docker เป็นเรื่องใหม่สำหรับคุณ คำศัพท์ต่างๆ นั้นง่ายกว่าที่คิด Docker image คือพิมพ์เขียว (blueprint) ซึ่งประกอบด้วย source code, Node.js runtime, lockfile และ dependencies ทุกอย่างที่จำเป็นในการรันแอป ส่วน container คือ instance ที่ทำงานอยู่จริงซึ่งสร้างมาจาก image นั้น ให้ลองนึกภาพว่า image คือสูตรอาหาร และ container คืออาหารจานจริง คุณสามารถอบเค้กแบบเดิมได้เป็นร้อยครั้งจากสูตรเดียว และคุณสามารถสร้าง container ที่เหมือนกันทุกประการจาก image เดียวกันได้ โดยไม่ต้องกังวลว่ามีอะไรติดตั้งอยู่ในเครื่องคอมพิวเตอร์หลักบ้าง
ตัวอย่าง Dockerfile ที่ใช้งานได้จริง
เรามาดูจุดเริ่มต้นที่เป็นรูปธรรมกัน หากคุณกำลัง
