DEV Community

Nattrio
Nattrio

Posted on

มือใหม่หัด Go: Docker Multi-stage Builds

สวัสดีชาว 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 ทั้งสองรูปแบบ

  1. ใช้ 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" ]
Enter fullscreen mode Exit fullscreen mode
  1. ใช้ 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" ]
Enter fullscreen mode Exit fullscreen mode

เมื่อ build เรียบร้อยทั้งสองรูปแบบ มาดูผลลัพธ์กันดีกว่า

multi-stage

จะเห็นว่าการใช้ 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)