Optimize Docker Build

Optimize Docker Build

สัปดาห์ที่แล้วผมได้ไป Odd-e boring gathering ที่หางโจวมา ชาว Odd-e ทั่วโลกจะมาเจอกันปีละ 2 ครั้งเพื่อแลกเปลี่ยนความรู้กัน

ครั้งนี้ ผมเลือกที่จะร่วมกันสร้าง product ขึ้นมาด้วยกันกับเพื่อนๆชาว Odd-e เราทำ Sprint 5 วัน รับ item มา 2 item จาก product owner เราตกลงกันว่าเราจะ pair programming กันทุกลมหายใจ มี techical requirement นิดหน่อยว่า architecture ต้องเป็นอย่างไร และทุกอย่างต้อง run อยู่ใน docker หลังตกลงกันเสร็จแล้ว sprint ก็เริ่มต้น

ทุก ๆ คน เก่งกันมาก ๆ ผมได้เรียนรู้เยอะมาก สมศักดิ์ศรีทีมที่สมาชิกแต่ละคนเป็นโค้ชมือพระกาฬจากทั่วโลกมารวมตัวกันจริง ๆ

จบ sprint ปรากฏว่าไม่มีห่าอะไรเสร็จเลย… เวลาส่วนใหญ่เราเสียไปกับการ download maven package กับ download npm package สิ่งสำคัญที่ผมได้เรียนรู้จากประสบการณ์ sprint นี้คือ

เวลาเขียน docker file ให้แยกจังหวะ download dependency libraries กับ compile code ออกจากกัน

ลองดูตัวอย่าง Dockerfile ด้านล่าง

FROM maven:slim as build-stage
COPY ./ ./
RUN mvn install
CMD mvn spring-boot:run

(Gist) https://gist.github.com/juacompe/1733f108197e6eb22b5e2e9180547e70

ตั้งต้นจาก maven image แล้ว copy code แล้วก็สั่ง build แล้วก็ run ดูตรงไปตรงมา ปัญหาคือ ทุก ๆ ครั้งที่เราแก้โค้ด บรรทัดที่ 2 จะ dirty แล้วมันจะต้องทำ mvn install ใหม่ (ซึ่งจังหวะนี้จะ download libs ทั้งหลาย) ทุกครั้ง…

ลองมาดูอันที่แยกจังหวะ download กับจังหวะ build กัน

FROM maven:slim
# copy pom file
COPY ./pom.xml ./
# download all dependency libraries
RUN mvn dependency:go-offline -B
# copy the rest of the code
COPY ./ ./
# build package
RUN mvn install
CMD mvn spring-boot:run

(Gist) https://gist.github.com/juacompe/6b522ed46f26c4953657d7264ed13703
separate library downloading and package building

พอแก้เป็นแบบนี้ ตราบใดที่ pom.xml ไม่ถูกแก้ ตอนสั่ง docker build มันจะใช้ cache ไปจนถึงบรรทัดที่ 7 ( COPY ./ ./ ) ซึ่งทำให้ไม่ต้อง download libs ทั้งหลายใหม่ ทำให้มันเร็วขึ้นมาก

นอกจากนี้ ขณะที่เรากำลังแก้ Dockerfile เราไม่ได้แก้โค้ดเลย แต่พอสั่งบรรทัดที่ 7 ที่มัน copy ทุกอย่าง มันก็จะต้อง build ใหม่ทุกครั้ง ทำไงดี?

เราสามารถกำหนด file ที่เราจะไม่ copy เข้าไปใน image ได้ ใน file ชื่อ .dockerignore ครับ

Dockerfile
.dockerignore
.git/


(Gist) https://gist.github.com/juacompe/d09c0fb42c166af643591ed01b00f25d
.dockerignore

file นี้ระบุว่า ไอ้ file Dockerfile ,.dockerignore และ.git เนี่ย ไม่ต้องเอาเข้าไปนะ เพราะใน container ไม่จำเป็นต้องใช้

เพียงแค่นี้ เราก็สามารถ get feedback เร็ว ๆ เวลาที่เราแก้ Dockerfile แล้วจะลอง run docker build ดูได้แล้วครับ

ถ้าอยากประหยัดเวลามากกว่านี้ทำไง?

มี 3 ทางถ้าอยาก optimize มากกว่านี้ ประกอบด้วย 1 ทางสวย ๆ และอีก 2 ทางสกปรก ๆ หน่อย

ทางแรก คือ สร้าง dockerhub ขึ้นมา host เอง เพื่อจะได้ไม่ต้องไป load image จาก internet ทางนี้สวยสุด ทำยากไหม? แล้วแต่ความชำนาญ ผมเห็น Chai Feng (เพื่อนจาก Odd-e ทีมเซี่ยงไฮ้) ทำ 10 นาที

ทางที่สองคือ สร้าง docker image ใหม่ที่ download dependency libs เสร็จแล้ว แล้ว push ขึ้น docker hub เพื่อใช้เป็น base image ต่อให้ pom.xml เปลี่ยน ก็ download เพิ่มไม่เยอะ

ทางที่สามคือ mount path ที่ใช้ในการเก็บ dependency libraries (~/.m2e/) ออกมาใส่เครื่อง host แบบนี้เราจะได้ใช้ประโยชน์จาก caching ของ maven เอง

ถ้าเป็น node project ทำไง?

ใช้ idea เดียวกันครับ คือ copy package.json กับ package-lock.json เข้าไปก่อน แล้ว run npm install แยกกันกับ npm build

credit: http://whitfin.io/speeding-up-maven-docker-builds/ สำหรับคำสั่ง download mvn dependencies

ref: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

Read more

การสร้างทีม

การสร้างทีม

เคยไหม ที่เรามารวมตัวกับทีมเพื่อทำอะไรสักเรื่องที่ยาก ๆ แล้วพอทำ ๆ ไปก็เริ่มกังวลว่า เอ๊ะ นี่ทุกคนยังอยากทำสิ่งนี้อยู่ไหมนะ ทุกคนในทีมเต็มในทำมันหรือเปล่า ความลังเลตรงนี้มักจะทำให้เราไม่กล้าใส่แรงสุดกับงานนั้้น แล้วเริ่มแบ่งกำลั

By Chokchai
Long lived team

Long lived team

ทุกวันนี้สกรัมเป็นที่นิยมมากในทีมพัฒนาซอฟต์แวร์ จากประสบการณ์ที่ผมพบเจอทีมหลากหลาย มีน้อยทีมนักที่จะทราบว่า สกรัมออกแบบมาให้ทีมอยู่กันเป็น long lived team และน้อยคนยิ่งกว่านั้นที่จะเข้าใจทั้งความหมายของคำว่า long lived และคำว่าทีม Team ทีมไม่ใช่

By Chokchai
เสน่ห์ของ ScrumMaster

เสน่ห์ของ ScrumMaster

บางครั้งผมจะได้ยินคำถามเวลาไปงานแลกเปลี่ยนความรู้กับวง ScrumMaster ว่า ทำไงดี ทีมไม่เปิดใจให้ เข้าถึงทีมยาก ตอนผมนั่งในวงนั้น ผมก็ไม่รู้จะตอบยังไง เพราะผมไม่มีปัญหานี้ วันก่อน มีเพื่อนร่วมงานให้ feedback ผมว่า ผมมีพลังพิเศษ ทำให้คนไว้ใจ อยากเข้ามาปรึ

By Chokchai
ความหมายของที่ซ่อนอยู่ใน Just In Time

ความหมายของที่ซ่อนอยู่ใน Just In Time

วันหนึ่ง มีเด็กน้อยคนหนึ่ง กำลังจะขึ้นเครื่องบิน เด็กน้อยร้องไห้กระจองอแง อยู่ตรง security check เพราะว่าปลาทองที่เค้าจับมาได้ 2 ตัวนั้น ไม่สามารถเอาขึ้นเครื่องได้ เพราะมีน้ำอยู่ ยิ่งเด็กร้องนาน พ่อแม่ก็ยิ่งเครียด แล้วก็

By Chokchai