เรียนรู้ multi-stage docker ด้วยการ deploy react ขึ้น production กันเถอะ

Thanatcha Kromsang
2 min readFeb 14, 2019

--

หลังจากที่อู้จากการเขียน blog ภาคต่อของ มาจับ React ยัดใส่ Container กันเถอะ! มาเป็นเวลาก็ถึงเวลาอันสมควรแล้วที่จะพา react ของเราขึ้นสู่โปรดัคชั่น อย่างง่าย ๆ ด้วยการทำ multi-stage docker ว่าแต่ multi-stage docker นี่มันคืออะไรกันนะ?

Multi-stage build คืออะไร และมีประโยชน์อย่างไร?

เรื่องที่จัดการยากสุด ๆ สำหรับการ docker นั้นคือเรื่องขนาด docker images ซึ่งในกรณีของ react นั้นสามารถมี images ขนาดใหญ่ถึง 1 GB ถ้าหากบอกว่าสามรถทำให้ขนาด images ขนาดเหลือเพียง 15 MB ได้จะเชื่อกันหรือเปล่า!

ไม่ได้โม้นะเว้ย

โดยเราสามารถลดขนาดของ docker images ให้เหลือเพียง 15 MB ได้โดยการใช้ multi-stage build ไงล่ะ แล้วการทำ multi-stage build คืออะไรล่ะ อธิบายอย่างง่าย ๆ คือการที่เรานำสิ่งของที่ถูกสร้างบางส่วนจาก images ที่หนึ่งไปใส่ในอีก images หนึ่งนั่นเองถ้าถึงตรงนี้แล้วยังไม่ค่อยเข้าใจ ไม่เป็นไรเดี๋ยวพาไปลุยของจริงกันเลยดีกว่า

เตรียมตัวก่อนทำ Multi-stage build docker

  • Create React App
  • Docker CE 17.05+

ทำการติดตั้ง create-react-app

$ npm install -g create-react-app

ทำการติดตั้ง Docker ซึ่งขั้นตอนของแต่ละ OS มีความแตกต่างกัน แนะนำให้ศึกษาขั้นตอนการติดตั้งผ่านลิงค์ข้างล่าง

มาเริ่มทำ Multi-stage build กันเลย!

หลังจากติดตั้งทุกอย่างสำเร็จแล้วก็ทำการ generate react project ขึ้นมา

$ create-react-app react-multistage
$ cd react-multistage

หลังจากนั้นทำการสร้าง Dockerfile ขึ้นมาภายในโปรเจคแล้วใส่ instruction ตาม code ด้านล่าง

# Dockerfile
# 1st Stage
FROM node:10.15.1 AS builder
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json .
COPY yarn.lock .
RUN yarn install --ignore-platform
COPY . .
RUN yarn build
# 2nd Stage
FROM nginx:1.14.2-alpine
COPY --from=0 /usr/src/app/build /usr/share/nginx/html
WORKDIR /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]

จากนั้นทำการ build images ด้วยคำสั่ง

$ docker build -f Dockerfile -t react-multistage:latest .

จาก Dockerfile เบื้องต้นนั้นสามารถอ่าน instruction คร่าว ๆ ได้ดังนี้

  • ขั้นที่ 1 — สร้าง production build ของ react เก็บไว้ที่ /usr/src/app/build ของ image แรก
  • ขั้นที่ 2 — คัดลอกเพียง production build จาก image แรกไปไว้ใน folder /usr/share/nginx/html ของ image ที่สองซึ่ง image ที่สองนั้นคือ nginx ซึ่งทำหน้าที่ในการเสิร์ฟ production build

หลังจากนั้นเราก็จะได้ docker image ที่เก็บเพียงแค่ production build ไม่มี code และ node modules ของโปรเจคเราอยู่เลย ทำให้มีความโล่งมาก ๆ

ทดสอบด้วยการใช้ docker run ว่าสามารถเปิดใช้งาน docker images นั้นได้จริงไหม ด้วยคำสั่งด้านล่างเพื่อเปิด port 80 หรือ HTTP

$ docker run --rm -p 80:80 react-multistage:latest

ผลลัพธ์:

สวยงามมาก ๆ

สรุป

  • multi-stage build นั้นช่วยลดขนาดของ image สุดท้ายได้อย่างมหาศาล
  • ในกรณีของภาษาที่ compiled เป็น binary เช่น golang สามารถคัดลอก binary ไปเพื่อใช้รันบน image เปล่า ๆ ได้ ทำให้ code ก่อน compile นั้นไม่ถูกเก็บบน docker image แน่นอนว่าแปลว่า code ไม่หลุดแน่ๆ
  • ลดจำนวนของ Dockerfile ภายใน project ขนาดใหญ่ ๆ ได้โดยสามารถเลือก build แต่ละ stage เพื่อใช้งานได้ ไม่จำเป็นต้อง build ทั้งหมด

ขอจบเพียงเท่านี้

Happy coding ❤

ศึกษาเพิ่มเติม code ได้ที่ React Multistage Docker Github Repository

--

--

Thanatcha Kromsang

Software Engineer | Vim Enthusiast | Linux Lover | Neccessary DevOps | Full-stack Developer | ❤ Graphql