พอดีในวงกินเบียร์มีการพูดคุยเรื่องการใช้งาน Docker สำหรับการพัฒนาระบบงาน
ซึ่งมันมีทางเลือกในการใช้งานหลากหลายแนวทางมาก ๆ
ดังนั้นจึงสรุปไว้กันลืมนิดหน่อย
ว่าคุยอะไรไปบ้าง (เท่าที่จำได้น่าจะคุยและ demo ให้ดูประมาณไม่เกิน 10 นาที)
มาเริ่มกันเลย

เริ่มจากปัญหาคือ Work on my machine

นักพัฒนานั้นก็จะทำการเขียน code
ติดตั้ง library/dependency
ทำการ build/compile
จัดการข้อมูลต่าง ๆ ใน database
แน่นอนว่า ทุกอย่างมัน work หรือทำงานได้ตามที่คาดกวังบนเครื่องนักพัฒนา

แต่เมื่อไปติดตั้งสิ่งต่าง ๆ ที่พูดมาข้างต้นแล้ว บนเครื่องอื่น ๆ
ยกตัวอย่างเช่น CI server, Dev/Test/Staging/Production กลับไม่ได้ !!
ต้องใช้เครื่องมือและวิธีการที่ต่างออกไป
สุดท้ายก็ไม่เหมือนกันอีกแล้ว
มันยังไงกันนะ !!

ยกตัวอย่างของปัญหา
เครื่องนักพัฒนาใช้ Mac OS
พัฒนาระบบงานด้วยภาษา Go
จัดการ dependency ด้วย go mod
ทำการ compile และ build เป็น binary file
ทำการทดสอบทั้ง Unit test และ Integration test
ทำการ deploy และติดตั้งระบบงานด้วยการนำ binary file ไป run
เพียงเท่านี้ก็จบแล้ว

ปัญหาที่พบเจอบ่อย ๆ คือ

  • Version ของภาษา Go ที่ต่างกัน
  • Binary file ที่สร้าง และ deploy ใน environment ต่าง ๆ มีปัญหา เพราะว่าใช้ OS ต่างกัน
  • การทำ integration test ยากมาก ๆ

การแก้ไขปัญหาพื้นฐานคือ
การคุยและตกลงร่วมกัน
ส่วนการ build และ deploy ก็เขียนMakefile และ shell script ไว้ใน project
ให้ทุกคนใช้งานร่วมกัน
เพียงเท่านี้ก็แก้ไขปัญหาได้แล้ว

แต่พวก Makefile และ shell script ต่าง ๆ ต้องรับค่าต่าง ๆ จากผู้ใช้งานด้วย
เช่น นักพัฒนาต้องการ build บน Mac OS ก็ต้องค่าพวก platform/architecture ของ Mac เข้าไป
ผลที่ออกมาคือ ยังมีข้อผิดพลาด

ส่วนเรื่องของ version ของภาษา Go ก็ยังเกิดขึ้น
แต่ไม่ค่อยส่งผลมากเท่าไร

จากปัญหาต่าง ๆ ที่ยังเกิดขึ้น เลยมีการพูดถึงการนำ Docker มาใช้งาน

ซึ่งการใช้งานต้องแบ่งออกเป็นขั้นตอนแยกกันดังนี้
อย่าเอามารวมกันนะ ไม่งั้นมั่วแน่นอน

  1. Docker สำหรับการพัฒนาบนเครื่องของนักพัฒนาแต่ละคน
  2. Docker สำหรับการทดสอบ
  3. Docker สำหรับการ deploy

1. Docker สำหรับการพัฒนาบนเครื่องของนักพัฒนาแต่ละคน

เริ่มง่าย ๆ คือ ติดตั้ง Docker ก่อนนะ กินทรัพยากรมากพอดู
ดังนั้นเครื่องนักพัฒนาต้องแรงพอตัว
เมื่อเครื่องพร้อมก็ไปเลือก Docker Image ของภาษา Go ที่ต้องการจาก Docker Hub
ใช้งานง่าย ๆ ด้วย command line ดังนี้

ตัวอย่างใช้ภาษา Go version 1.11.2 บน Alpine OS
Code ตัวอย่างที่พอจะเขียนได้ตอนนั้น

ทำการ compile และ run ด้วย Docker ดังนี้

# Run
$docker container run --rm -w /xxx -v $(pwd):/xxx golang:1.11.2-alpine3.8 go run hello.go

# Build binary file และ Run
$docker container run --rm -w /xxx -v $(pwd):/xxx golang:1.11.2-alpine3.8 go build -o ./app
$docker container run --rm -w /xxx -v $(pwd):/xxx golang:1.11.2-alpine3.8 ./app

แต่ถ้าเบื่อ command line เยอะ ๆ ก็สร้าง Dockerfile มาใช้ซะ
เริ่มจากสร้างไฟล์ Dockerfile_dev สำหรับทำการ compile/build/run ระบบงาน

ทำการ run ด้วยคำสั่ง

$docker image build -t demo -f Dockerfile_dev .
$docker container run --rm demo

2. อย่าลืมเพิ่มส่วนของการทดสอบ และพวกการจัดการ library/dependency เข้าไปด้วยนะ

เริ่มด้วยการเขียน Dockerfile_testing ขึ้นมา

ทำการ run ด้วยคำสั่ง

$docker image build -t demo -f Dockerfile_testing .
$docker container run --rm -t demo

3. อีกส่วนคือการใช้ Docker สำหรับการ deploy

สิ่งที่แนะนำไปคือ การใช้งาน Multi-stage build สำหรับการสร้าง Docker Image
เพื่อให้ได้ Docker Image ที่มีของเท่าที่จำเป็น
เนื่องจากตอนนี้ Docker Image ของระบบจากขั้นตอนที่ 1 และ 2 มันใหญ่มาก
เพราะว่ามีทั้ง Go และอื่น ๆ อีกมากมาย
แต่ในการ deploy ระบะบบงานของเรานั้น
ต้องการเพียงนำ binary file ไปติดตั้งบน OS ที่ต้องการเท่านั้น

ดังนั้นมาใช้งาน Multi-stage build กัน
ทำการสร้าง Dockerfile ดังนี้

ทำการ run ด้วยคำสั่ง

$docker image build -t demo -f Dockerfile .
$docker container run --rm -t demo

ส่งผลทำให้ขนาดของ Docker Image ของระบบงานเราเล็กลงไปอย่างมาก
จากตัวอย่างนี้ลดจาก 431 MB เหลือเพียง 6.92 MB เท่านั้นเอง

ตัวอย่าง code อยู่ที่ Github:Up1:Demo with Go

เพียงเท่านี้เราก็สามารถนำ Docker มาใช้ในการพัฒนาระบบงานได้อย่างแจ่มแล้วนะครับ
ถ้าไม่อยากเขียนเยอะ ๆ ก็ไปใช้ Docker Compose ต่อไปนะ
ขอให้สนุกกับการ coding ครับ