Optimize Docker Image ให้เล็กลงด้วย Multi-Stage Build

Docker images ที่ใหญ่เกินไปจะใช้ storage เยอะ, นาน Deploy, และ Pull ช้า ปัญหานี้ที่สำคัญมากในการจัดการ Docker Infrastructure ที่มีประสิทธิภาพ Multi-Stage Build เป็นวิธี best practice ที่ช่วยให้ image ขนาดเล็กลง

Multi-Stage Build คืออะไร?

Multi-Stage Build คือเทคนิคการ build Docker image โดยใช้หลาย stage ในไฟล์ Dockerfile เดียว โดยแต่ละ stage สามารถ build artifact ต่างๆ และ stage สุดท้ายจะนำเฉพาะสิ่งที่ต้องการมาใส่ใน final image

ตัวอย่าง: Go Application

สำหรับ Go Application เราสามารถใช้ multi-stage build เพื่อลด image size ได้มาก โดย stage แรก build binary จากโค้ด source และ stage ที่สอง นำแค่ binary มาใส่ใน image ที่เล็ก

FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .

FROM alpine:latest
COPY --from=builder /app/myapp /usr/local/bin/
CMD ["myapp"]

ตัวอย่าง: Node.js Application

สำหรับ Node.js เราใช้ multi-stage เพื่อแยก build stage และ production stage

FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:18-alpine
COPY --from=builder /app/node_modules /app/node_modules
COPY . .
CMD ["node", "index.js"]

Advanced: Multi-Stage ด้วยหลาย Stage

บางครั้ง อาจต้องใช้มากกว่า 2 stage เพื่อ optimize build process อย่าง tests, linting, และสุดท้าย production image

ข้อดีของ Multi-Stage Build

  • ลด image size อย่างมาก (ลบ build dependencies ออก)
  • เร็วขึ้นในการ pull image จาก registry
  • ประหยัด storage space
  • ปลอดภัยมากขึ้น (ไม่มี source code ใน final image)

Best Practices สำหรับ Multi-Stage Build

  • ใช้ specific image tags (ไม่ใช่ latest)
  • ลบ unnecessary files ในแต่ละ stage
  • ใช้ .dockerignore เพื่อไม่ copy ไฟล์ที่ไม่จำเป็น
  • วาง COPY commands ไว้หลัง RUN commands ที่มีความเสี่ยง
  • ใช้ Alpine Linux สำหรับ final stage