เทคนิคการเขียน Dockerfile ให้ดีขึ้นกว่าเดิม

--

Intro Guide to Dockerfile Best Pracetices

วันนี้จะมาแชร์เทคนิคต่างๆ สำหรับการใช้งาน Dockerfile ให้มีประสิทธิภาพมากขึ้นนะครับ ก่อนอื่นขอย้อนกลับไป พูดถึง Dockerfile กันสักหน่อย ว่าคืออะไร มีหน้าทีอะไร

Dockerfile คือ text document ที่ระบุการใช้งานและคำสั่งทั้งหมด เพื่อเอาไว้ประกอบร่าง Docker Image ขึ้นมา โดยใช้คำสั่ง docker build เพื่อสร้างเป็น Docker Image

Example [Dockerfile]

*หมายเหตุ ตัวอย่างด้านล่าง จะเป็นการเขียนโปรเจค Java บน Maven

Incremental build time — เวลาในการสร้าง build

ในการพัฒนาโปรแกรม เมื่อเราต้องการสร้าง Docker Image ในครั้งแรกจะยังไม่มีการใช้งานในส่วนของ Caching แต่เมื่อเรามีการเปลี่ยนแปลงโค๊ดแล้วทำการสร้าง Docker Image อีกครั้ง เราจะสามารถใช้งานในส่วนของ Caching นี้ได้ ทำให้เราสามารถลดเวลาในการ Build ได้นะครับ

Tip #1: Order matters for caching

Order matters for cahcing

ลำดับของการรันคำสั่งมีความสำคัญ​ โดยเราถ้าเรามีการเปลี่ยนแปลงไฟล์หรือแก้ไขคำสั่งใน Dockerfile จะทำให้ Caching ไม่สามารถใช้งานได้ เราจึงควรนำคำสั่งที่มีการเปลี่ยนแปลงบ่อยๆ ย้ายไปอยู่ด้านล่างแทน ดังรูปด้านบน

Tip #2: More specific COPY to limit cache busts

More specific COPY to limit cache busts

ถ้าเป็นไปได้เวลาใช้งานคำสั่ง COPY ในการก๊อปปี้โค๊ดเข้าไปใน Docker Image ให้เราควรหลีกเลี่ยงการใช้งาน “COPY .” (คำสั่งนี้จะก๊อปปี้ไฟล์ทั้งหมดในโฟลเดอร์นั้น ) ให้ใช้งานเป็นระบุโฟลเดอร์ที่ต้องการแทนจะดีกว่า เพราะเมื่อเรามีการแก้ไขไฟล์แค่โฟลเดอร์เดียวหรือไฟล์เดียว จะทำให้ Cahcing ไม่สามารถใช้งานได้

Tip #3: Identify cacheable units such as apt-get update & install

Line buddies: apt-get update & install

เมื่อเราเขียนคำสั่ง RUN แต่ละบรรทัด การทำ Caching จะแยกกัน เราควรวิเคราะห์คำสั่งที่ทำงานด้วยกันเสมอ มารันด้วยกัน เช่น apt-get update กับ apt-get -y install [package] มาทำงานด้วยกัน เพราะปกติเราจะทำการอัพเดทก่อนเพื่อให้เราสามารถใช้งาน package ในเวอร์ชั่นล่าสุดเสมอ

Reduce Image size — ขนาดของ Docker Image

ในหัวข้อนี้จะพูดเกี่ยวกับเทคนิคการลดขนาดของ Docker Image

Tip #4: Remove unnecessary dependencies

Remove unnecessary dependencies

เราควรลบแพคเกจที่ไม่จำเป็นต้องใช้งานในการรันโปรแกรมหรือสิ่งที่ใช้ในการดีบั๊กต่างๆ เช่น vim ssh ออกไปนะครับ ถ้าเราอยากดีบั๊ก เราสามารถลงที่หลังได้ถ้าเราต้องการ
บางครั้งเวลาเราลงแพคเกจต่างๆ จะมีการติดตั้งแพคเกจแนะนำต่างๆมาด้วย เราสามารถใส่คำสั่ง — no-install-recommends เพื่อลงเฉพาะที่เราต้องการใช้งานเท่านั้น

Tip #5: Remove package manager cache

Remove package manager cache

เวลาเราทำการติดตั้งแพคเกจต่างๆ ส่วนใหญ่จะมีการทำ caching ไว้ เพื่อใช้ครั้งต่อไป ซึ่งไม่มีความจำเป็นเมื่อเราใช้งาน Docker Image นะครับ เพราะเราจะทำการ build ใหม่ทุกครั้ง ทำให้เราสามารถลบในส่วนนี้ได้เลยหลังจากเราติดต่อเรียบร้อย

Maintainability — การบำรุงรักษา

Tip #6: Use official images when possible

Use officail images when possible

เราควรเลือกใช้ image จากทางผู้พัฒนาหลัก เพื่อลดเวลาในการบำรุงรักษาต่างๆ เช่น package, security เป็นต้น

Tip #7: Use more specific tags

Use more specific tags

อย่าพยายามใช้แท็ก latest เพราะเมื่อเราทำการ build ใหม่ ทางโปรแกรมจะทำการดึง image เวอร์ชั่นล่าสุดมาใช้งานเสมอ เพราะฉะนั้นโปรแกรมของเรายังไม่ซัพพอร์ตหรือในเวอร์ชั่นนั้นๆ มีการอัพเดทเปลี่ยนแปลงเยอะ มีโอกาสทำให้โปรแกรมของเราไม่สามารถทำงานได้ ทางที่แนะนำ คือ ให้ระบุเวอร์ชั่นที่เราต้องการเข้าไป แล้วทำการเปลี่ยนเองเมื่อเราต้องการอัพเดทนะครับ

Tip #8: Look for minimal flavours

Look for minimal flavours

เลือกใช้งาน tag ให้เหมาะสม เพราะแต่ละ tag มีขนาดไม่เท่ากัน ขึ้นอยู่กับโปรแกรมของเรานะครับ ว่าต้องการ OS แบบไหน โดยที่ยอดนิยมจะเป็น alpine ซึ่งจุดเด่น คือ จะมีขนาด image ที่เล็กมาก ทำให้หลังจาก build แล้ว มีขนาดเล็กมากและในบางครั้งยังทำให้ใช้งานทรัพยากรเครื่องน้อยกว่าด้วยนะครับ

Reproducibility

Tip #9: Use multi-stage builds to remove build dependencies (recommended Dockerfile)

Multi-stage builds to remove build deps

อันนี้เป็นอีกทีนึงที่เรียกว่าการใช้งาน multi-stage เพื่อลดระยะเวลาในการBuild เพราะจะทำการ cahce ไว้แล้ว

  • เราสามารถทำการใช้งานคำสั่ง AS [STAGE_NAME] ดังรูปด้านบน
  • ขั้นตอนต่อไป เราจะทำการอ้างอิงจากไฟล์ที่เราทำการ build ไว้แล้วในข้างต้น โดยใช้คำสั่ง COPY — from=[STAGE_NAME] โดยในเคสนี้จะใช้ชื่อว่า builder

Multi-stages builds จะช่วยทำให้เราลดเวลาในการรันคำสั่งในส่วนของการลงแพคเกจต่างๆ ก๊อปปี้ไฟล์ ได้นะครับ

ก็จบไปแล้วนะครับ สำหรับเทคนิคเพื่อทำให้เราเขียน Dockerfile ให้มีประสิทธิมากขึ้นนะครับ ยังไงถ้ามีส่วนไหนสงสัยหรือผิดพลาด สามารถคอมเม้นได้เลยนะครับ

Reference : https://blog.docker.com/2019/07/intro-guide-to-dockerfile-best-practices

คิดและเขียนคือสิ่งที่ผมชอบ ได้ทดลองทำอะไรใหม่ๆ เพื่อนำมาประยุกต์และต่อยอดในเรื่องต่างๆ พร้อมถ่ายทอดเรื่องราวจากชีวิตจริง จากประสบการณ์ จากแนวคิดของผม :)

--

--