![]()
![]()
วันนี้ไปดู release note ของ
Docker edge version (v17.05.0 ce) พบว่า
มีความสามารถที่กำลังต้องการคือ
Multi-stage build
ซึ่งช่วยทำให้การสร้าง image ของระบบงานได้ง่าย และสะดวกขึ้น
ที่สำคัญยังช่วยลดขนาดของ image อีกด้วย
มาลองใช้งานกันดู
ก่อนอื่นมาดูขั้นตอนการสร้าง image แบบปกติกันก่อน
ระบบตัวอย่างเป็นการสร้าง image ของระบบที่พัฒนาด้วยภาษา Go
ซึ่งส่วนใหญ่มักจะสร้าง image ขึ้นมาสองตัวคือ
- สำหรับทำการ build เพื่อ compile และสร้างไฟล์ binary ของระบบ
- สำหรับการ deploy นั่นคือทำการทำเอาไฟล์ binary จาก image ตัวที่ 1
ปล. บางคนก็ทำเพียง image เดียวเท่านั้น
แต่ผลที่ได้คือ ขนาดของ image ที่ใหญ่มาก ๆ
เพราะว่ามีทั้ง OS + Golang (257MB), Library และ source code
ทั้ง ๆ ที่เราต้องการเพียง OS และไฟล์ binary เท่านั้นเอง !!
ดังนั้นขอแนะนำให้ทำเป็น 2 image น่าจะดีกว่า
ซึ่งวิธีการนี้เราเรียกว่า
Builder pattern
ดังนั้นต้องสร้าง Dockerfile ขึ้นมา 2 ไฟล์ (ชีวิตดูลำบาก)
การนำไฟล์ binary จาก container หนึ่งไปอีก container หนึ่งทำอย่างไร ?
เช่นการ map volume หรือ copy ข้าม container กันเลย
ตัวอย่าง script ของการใช้งาน
[gist id="c6c98aae33c7d43126147b914e052a12" file="build.sh"]
ผลที่ได้คือ image 2 ตัวดังนี้
[gist id="c6c98aae33c7d43126147b914e052a12" file="build.txt"]
จากนั้นทำการสร้าง container จาก image ที่ได้คือ my_image:latest เช่น
[code]
$docker container run --rm -p 8080:8080 my_image:latest
[/code]
ปกติก็ใช้วิธีนี้กัน ซึ่งก็ใช้งานได้ดีนะ
มาดูกันต่อสิว่าแล้ว Multi-stage build มันเป็นอย่างไร ?
จากวิธีการข้างต้น ต้องจัดการ Dockerfile 2 ไฟล์
ซึ่งดูลำบากน่าดู
ดังนั้นจะดีไหม ถ้ายุบให้เหลือเพียงไฟล์เดียว น่าจะสบายขึ้นไหม ?
จากวิธีการข้างต้น จะสร้าง image ขึ้นมา 2 ตัว
ซึ่งต้องลบ image ตัวแรกออกไปตลอด
ดังนั้นจะดีไหม ถ้าเราสร้างไฟล์ image เดียวไปเลย
เราสามารถเขียน Dockerfile แบบใหม่ได้ดังนี้
[gist id="c6c98aae33c7d43126147b914e052a12" file="Dockerfile_multi"]
คำอธิบาย
- COPY --from=0 คือการบอกว่าให้ copy ข้อมูลจาก image แรก โดยเริ่มจากตำแหน่งที่ 0
- หรืออาจจะใช้ COPY --from=build ก็ได้นะครับ ทำให้อ่านเข้าใจง่ายขึ้นอีก
- จากตัวอย่างทำการ copy ไฟล์ app ซึ่งเป็นไฟล์ binary มายัง image ที่สอง
ทำการสร้าง image ด้วยคำสั่ง
[code]
$docker image build -t my_demo . -f Dockerfile_multi
[/code]
จากนั้นก็ทำการสร้าง container จาก image ชื่อว่า
my_demo
เพียงเท่านี้ก็เป็นอันเรียบร้อย
สำหรับการเริ่มใช้งาน Multi-stage build
ง่ายขึ้นไหมนะ ?
ตัวอย่าง source code และ configuration ต่าง ๆ อยู่ที่
Github::Up1::Docker with Multi-stage build