สวัสดีชาว Gopher ทุกท่าน ในปัจจุบันการใช้ Container สำหรับพัฒนาแอปอย่าง Docker เป็นที่นิยมอย่างมาก เนื่องจากช่วยในการจัดการ environment และ library ให้เหมือนกันได้ไม่ว่าจะอยู่ที่ไหนก็ตาม
อย่างไรก็ดี ปัญหาการ "บวม" (Docker image bloating) หรือก็คือ image มีขนาดใหญ่เกินความจำเป็นนั้น สามารถเกิดขึ้นได้ถ้าไม่จัดการให้ดี ทางออกอื่นๆ ที่ช่วยได้ เช่น
- ใช้
dockerignore
เพื่อไม่ให้เพิ่มไฟล์ที่ไม่ต้องการ - เลือกใช้ distroless/minimal base image เพื่อลดขนาดให้ได้มากที่สุด
ต้องเข้าใจว่าส่วนที่ใช้ทำในตอน build แอปพลิเคชันนั้น พอเสร็จแล้วมักจะไม่ถูกนำมาใช้ต่อตอนที่แอปกำลังรัน ถ้าเรานำทั้งหมดมาใช้ก็จะทำให้บวมได้ ในบทความนี้จะนำเสนออีกวิธีที่จะแยกส่วนที่เป็น build tool ออก ให้เหลือเฉพาะส่วนที่จำเป็นต่อการรันแอปนั่นเอง เรียกว่า Multi-stage builds
Docker : Multi-Stage Builds
Multi-stage builds จะช่วยลดขนาดของ container ให้เล็กลงได้ ด้วยการแตกขั้นตอนออกเป็นหลายๆ stage ย่อย แต่ละ stage จะส่งผลลัพธ์ต่อไปยัง stage ถัดไป
Demo
เราสามารถใช้แอปนี้ GitHub เป็นตัวอย่างเบื้องต้นในทดสอบ
ในการเปรียบเทียบเพื่อให้เห็นภาพชัด จะทดสอบการ build ทั้งสองรูปแบบ
- ใช้ Dockerfile ในการ build แบบปกติ
FROM golang:1.18-alpine
WORKDIR /crud
COPY . .
RUN go mod download
EXPOSE 2565
RUN go build -o /test main.go
CMD [ "/test" ]
- ใช้ Dockerfile ในการทำ Multi-Stage build ซึ่งจะแบ่งเป็น 2 environment ที่แตกต่างกัน
# Build stage
FROM golang:1.18-alpine AS builder
WORKDIR /crud
COPY . .
RUN go mod download
EXPOSE 2565
RUN go build -o /test main.go
# Deploy stage
FROM alpine:latest
WORKDIR /
COPY --from=builder /test /test
EXPOSE 2565
USER nonroot:nonroot
ENTRYPOINT [ "/test" ]
เมื่อ build เรียบร้อยทั้งสองรูปแบบ มาดูผลลัพธ์กันดีกว่า
จะเห็นว่าการใช้ Multi-stage builds ช่วยลดขนาดให้ image ของเราอย่างมหาศาลเทียบกับแบบปกติ จาก 430 MB เป็น 16 MB พอเล็กแล้วก็สามารถนำไปใช้ต่อได้ง่ายมากขึ้นนั่นเอง
หวังว่าบทความนี้จะเป็นประโยชน์กับ Gopher และผู้ใช้ Docker ทุกคนกันนะครับ
Reference:
Optimizing Golang Docker images with multi-stage build | by Krishnadutt Panchagnula
Top comments (0)