DEV Community

Tossapol Ritcharoenwattu
Tossapol Ritcharoenwattu

Posted on

การเพิ่มความปลอดภัยให้กับ container (Non-root user , ลบ tool หรือ package ที่ไม่จำเป็น, File permission)

ถึงแม้ว่าเราจะใช้ base image จาก scratch , alpine แล้ว แต่สิ่งที่เราควรทำเพื่อเพ่ิมความปลอดภัยให้กับ container ของเราคือ

  1. run ด้วย non-root user
  2. remove tool/package ที่ไม่ได้ใช้ ทั้งหมดโดยเฉพาะ hack tool
  3. Set file permission
    • execution file : file permission = 500 (user can read & execute)
    • Other file : file permission = 400 (user can read only)

ทั้งหมดนี้ เราสามารถทำได้ใน Dockerfile
ตัวอย่างนี้ ใช้ todolist จาก workshop ที่แล้ว ใน api ที่สร้าง มีไฟล์ main.go ไฟล์เดียว จึงได้มีการสร้างไฟล์ app.secret ขึ้นมาเพื่อเป็นตัวอย่างการ set file permission 400

Base image : Scratch
Dockerfile

# Dockerfile.scratch
# Stage 1: Build the Go application
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
RUN echo "MY_SUPER_SECRET_API_KEY" > /app/app.secret

# --- Final Stage: scratch ---
FROM scratch
COPY --from=builder --chown=1000:1000 --chmod=400 /app/app.secret /app.secret
COPY --from=builder --chown=1000:1000 --chmod=500 /app/main /main
USER 1000
EXPOSE 8080
CMD ["/main"]
Enter fullscreen mode Exit fullscreen mode

ฺฺฺBuild image ด้วย command

docker build -t todo-api-secure-scratch -f Dockerfile.scratch .
Enter fullscreen mode Exit fullscreen mode

Image description

Base image : Alpine
สำหรับ alpine จะทำยากกว่า scratch เพราะต้องมีการลบไฟล์ที่ไม่จำเป็น หรือไฟล์ที่อาจเป็นช่องโหว่ในการโจมตีด้วย
ตัวอย่างคำสั่งที่ใช้ลบไฟล์

RUN apk --no-cache del gcc musl-dev curl netcat-openbsd && \
    rm -rf /var/cache/apk/*
Enter fullscreen mode Exit fullscreen mode

คำอธิบายแต่ละส่วน
RUN apk --no-cache del ...
apk: คือคำสั่งสำหรับจัดการ package ของ Alpine Linux (เหมือน apt ของ Debian/Ubuntu หรือ dnf ของ Rocky Linux)

del: เป็นคำสั่งย่อยของ apk ที่ใช้สำหรับ ลบ (delete) package
--no-cache: เป็น flag ที่บอกให้ apk ทำงานโดย ไม่เก็บไฟล์ชั่วคราว (cache) ไว้หลังจากทำงานเสร็จ ซึ่งช่วยลดขนาดของอิมเมจได้ทันที

gcc musl-dev curl netcat-openbsd: คือรายชื่อ package ที่ต้องการลบ ซึ่งล้วนเป็นเครื่องมือสำหรับนักพัฒนาหรือเครื่องมือที่อาจใช้ในการโจมตีได้
gcc, musl-dev: คือตัวคอมไพล์ภาษา C

curl: คือเครื่องมือสำหรับรับส่งข้อมูลผ่านเครือข่าย

netcat-openbsd: คือเครื่องมือเครือข่ายอเนกประสงค์

&& rm -rf /var/cache/apk/*
&&: คือตัวเชื่อมคำสั่ง ที่จะรันคำสั่งด้านขวา ก็ต่อเมื่อคำสั่งด้านซ้ายสำเร็จ

rm -rf /var/cache/apk/*: คือคำสั่ง ลบ (remove) ไฟล์และโฟลเดอร์ทั้งหมดใน /var/cache/apk/ ซึ่งเป็นที่เก็บ cache ของ apk

# Dockerfile.alpine
# Stage 1: Build the Go application
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# --- Final Stage: Hardened Alpine ---
FROM alpine:latest
RUN apk --no-cache del gcc musl-dev curl netcat-openbsd && \
    rm -rf /var/cache/apk/*
RUN addgroup -g 1000 swadm && \
    adduser -S -D -u 1000 -G swadm swadm
USER swadm
WORKDIR /home/swadm
RUN echo "MY_SUPER_SECRET_API_KEY" > /home/swadm/app.secret && \
    chmod 400 /home/swadm/app.secret
COPY --from=builder --chown=swadm:swadm /app/main /home/swadm/main
RUN chmod 500 /home/swadm/main
EXPOSE 8080
CMD ["./main"]
Enter fullscreen mode Exit fullscreen mode

Build image ด้วย command

docker build -t todo-api-secure-alpine -f Dockerfile.alpine .
Enter fullscreen mode Exit fullscreen mode

Image description

ลองใช้ trivy scan image ดูกันว่าเป็นอย่างไรกันบ้าง alpine ช่องโหว่จะเหลือ 0 หรือยังนะ???

Scratch
Image description

Alpine
Image description
ยังเหลือ 2 อยู่ดี เหตุผลคืือ
Image description
จากภาพจะเห็นว่าช่องโหว่ CVE-2025-4575 ซึ่งเป็นปัญหาที่พบใน base image alpine ที่เราใช้ ไม่ใช่ช่องโหว่จาก application ของเรา ใน library libcrypto3 มีสถานะเป็น "fixed" และคอลัมน์ "FIXED VERSION" ก็ระบุเวอร์ชันที่แก้ไขแล้วคือ 3.5.1-r0

บางครั้ง ถึงเราจะระบุ tag ให้ใช้ alpine เป็น version lastest แล้ว แต่ก็ยังต้องมีการส่งให้ upgrade package ที่ใช้ใน image เพิ่มเติม โดยเพิ่มคำสั่งนี้เข้าไปใน Dockerfile

apk upgrade
Enter fullscreen mode Exit fullscreen mode

หน้าตา Dockerfile ใหม่ที่ได้ คือ

# Dockerfile.alpine
# Stage 1: Build the Go application
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# --- Final Stage: Hardened Alpine ---
FROM alpine:latest

# --- เพิ่มบรรทัดนี้เข้ามา ---
# อัปเดต package ทั้งหมดเป็นเวอร์ชันล่าสุดเพื่อแก้ไขช่องโหว่
RUN apk upgrade --no-cache

# ลบเครื่องมือที่ไม่จำเป็นออก
RUN apk --no-cache del gcc musl-dev curl netcat-openbsd && \
    rm -rf /var/cache/apk/*

# ... (ส่วนที่เหลือของ Dockerfile) ...
RUN addgroup -g 1000 swadm && \
    adduser -S -D -u 1000 -G swadm swadm
USER swadm
WORKDIR /home/swadm
RUN echo "MY_SUPER_SECRET_API_KEY" > /home/swadm/app.secret && \
    chmod 400 /home/swadm/app.secret
COPY --from=builder --chown=swadm:swadm /app/main /home/swadm/main
RUN chmod 500 /home/swadm/main
EXPOSE 8080
CMD ["./main"]
Enter fullscreen mode Exit fullscreen mode

ทดสอบ build image alpine และ scan ด้วย trivy ใหม่อีกครั้ง
จะพบว่า ช่องโหว่ที่พบ เหลือ 0 แล้วครับ
Image description

Top comments (0)