4 ข้อที่แนะนำควรทำก่อน build docker container04 December 2020DevOps

4 ข้อที่แนะนำควรทำก่อน build docker container

มี 4 อย่างที่ผมแนะนำสำหรับคนที่ต้องการสร้าง Container ให้ดี ซึ่งมันจะทำให้ container นั้นมีขนาดเล็กลง และปลอดภัยมากขึ้น

1. Smaller Base image

ในตอนสร้าง Dockerfile ให้เราเลือก image ที่มีขนาดเล็กมาใช้เพื่อที่ container เราจะได้เล็กตามไปด้วย โดยส่วนใหญ่ให้สังเกตุ tag ของ image นั้นๆ จะมี alpine มาให้เลือกใช้ ซึ่งมันเป็น Linux ที่มีขนาดเล็ก เช่น Nodejs image

$ docker image ls
node        12          1f560ce4ce7e        7 weeks ago         918MB
node        12-alpine   d8b74300d554        8 weeks ago         89.6MB

สังเกตุว่าถ้าเราเอา node:12 มาใช้ขนาดมันคือ 918MB แม่เจ้า…

แต่ถ้าเราเลือก node:12-alpine จะเหลือขนาด 89.6MB ก็เลือกกันเอาเองว่าจะใช้อันไหน 🙂

2. Multi-stage builds

Multi-stage builds เป็น feature หนึ่งของ dockerfile ที่ทำให้เราสามารถ build docker ได้หลายๆ ชุดคำสั่งภายในไฟล์เดียว แล้วเอาชุดคำสั่งสุดท้ายมาใช้งาน

อาจจะยังไม่เข้าใจ ผมจะให้ดูโค็ดตัวอย่างละกันในการทำ reactjs ในรูปแบบ dockerfile เพื่อนำไปใช้งานได้เลย

# Stage 0, "build-stage", based on Node.js, to build and compile the frontend
FROM node:12-alpine as build-stage
WORKDIR /app
COPY package*.json /app/
RUN npm install
COPY ./ /app/
RUN npm run build

# Stage 1, based on Nginx, to have only the compiled app, ready for production with Nginx
FROM nginx:1.15-alpine
COPY --from=build-stage /app/build/ /usr/share/nginx/html

สังเกตุว่าเราสามารถใส่ FROM ได้ 2 อันใน Dockerfile ซึ่งปกติจะทำไม่ได้ ในกรณีนี้เราจะทำ 2 stage คือ

  1. ทำการติดตั้ง node_module แล้ว build reatjs ออกมาให้เป็น static ไฟล์
  2. นำ static ไฟล์ที่ได้มา ไปใช้งานบน nginx เพื่อให้สามารถเข้ามาดูเว็บได้

ซึ่งตอนสุดท้าย Docker image ตัวนี้เราจะได้เป็น nginx:1.15-alpine ที่มีไฟล์ reactjs แบบ static ไฟล์อยู่นั้นเอง

ศึกษาเพิ่มเติม: https://docs.docker.com/develop/develop-images/multistage-build/

3. Use of .dockerignore file

ในการ COPY ไฟล์เข้ามาใน docker image นั้นเราควรเลือกเฉพาะไฟล์ที่สำคัญสำหรับงานเราเท่านั้น เพื่อให้ image มีขนาดเล็กลง ซึ่งโดยปกติเราจะเขียน dockerfile กันแบบนี้

FROM node:12-alpine
COPY ./ /app/

การเขียน COPY ./ /app/ คือการเอาไฟล์ทั้งหมดเข้ามาใน docker image แต่หากเราไม่อยากได้ไฟล์บ้างอันละ ทำไง?

ก็เขียน .dockerignore ช่วยสิ วิธีเขียนจะเหมือนกับ .gitignore เลย และให้วางอยู่ในตำแหน่งกับ Dockerfile

$ ls -a
.  ..  .dockerignore  .eslintrc.json  .gitignore  Dockerfile  README.md  index.js   package.json  src/

ตัวอย่างการเขียน

$ cat .dockerignore
Dockerfile
README.md
.git/

4. Containers as a Non-Root User

โดยเริ่มต้น Docker image จะใช้ root user ในการใช้งาน ทำให้ถ้าใครสามารถเข้ามายัง container นี้ได้ก็สามารถใช้ได้ทุกคำสั่ง และสิ่งนี้เป็นสิ่งที่อันตรายมาก มันจะทำให้ container ที่เรานำไปใช้งานไม่ค่อยปลอดภัย

วิธีแก้ไขคือให้เราใช้ user อื่นในการใช้งาน container นั้น โดยมีวิธีเขียน dockerfile ดังนี้

FROM node:12-alpine
# Create a group and user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# Tell docker that all future commands should run as the appuser user
USER appuser
CMD [ "node", "index.js" ]

เพียงเท่านั้น node ของเราจะถูกเรียกใช้โดย appuser และหากมีใครเข้ามายัง container เราได้ ก็ไม่สามารถใช้คำสั่งสำคัญๆ ของระบบได้เช่นกัน

ก่อนหน้า
ถัดไป