
บทนำ: Container Security คืออะไร และทำไมสำคัญในปี 2026
Container Security หมายถึงกระบวนการและเครื่องมือทั้งหมดที่ใช้ปกป้อง Container Environment ตั้งแต่ขั้นตอนการสร้าง Container Image ไปจนถึงการ Deploy และ Run Container ใน Production ครอบคลุมทั้ง Container Image Security, Container Runtime Security, Container Orchestration Security (เช่น Kubernetes Security) และ Container Network Security โดยเป้าหมายหลักคือป้องกันไม่ให้ผู้ไม่หวังดีสามารถ Exploit ช่องโหว่ใน Container เพื่อเข้าถึง Host System หรือ Container อื่นๆ ที่อยู่บน Host เดียวกัน
ในปี 2026 การใช้ Container Technology อย่าง Docker และ Kubernetes ได้กลายเป็น Standard ขององค์กรแทบทุกขนาด จากรายงานของ CNCF Annual Survey พบว่ามากกว่า 90% ขององค์กรทั่วโลกใช้ Container ใน Production แต่การขยายตัวของ Container Usage ก็ทำให้ Attack Surface ขยายตัวตามไปด้วย ช่องโหว่ที่พบบ่อยใน Container Environment ได้แก่ Container Escape ที่ผู้โจมตีสามารถหลุดออกจาก Container ไปยัง Host System, Image Vulnerabilities ที่ Base Image มี CVE จำนวนมาก, Misconfiguration ที่ Container รันด้วย Root Privilege หรือมี Capability มากเกินไป และ Supply Chain Attack ที่ Image ถูกแทรก Malware ตั้งแต่ขั้นตอน Build
บทความนี้จะสอนทุกแง่มุมของ Container Security ตั้งแต่การทำ Docker Image Hardening เพื่อสร้าง Image ที่ปลอดภัย การ Scan หาช่องโหว่ การทำ Runtime Security เพื่อป้องกัน Container ที่กำลังรันอยู่ ไปจนถึง Kubernetes-specific Security และ Supply Chain Security เพื่อให้ Container Pipeline ทั้งหมดปลอดภัยตั้งแต่ต้นจนจบ
Container Security Risks ที่ต้องรู้
Container Escape
Container Escape เป็นภัยคุกคามร้ายแรงที่สุดใน Container Environment เกิดขึ้นเมื่อผู้โจมตีที่อยู่ภายใน Container สามารถหลุดออกมาและเข้าถึง Host Operating System ได้ ซึ่งหมายความว่าผู้โจมตีจะมีสิทธิ์เข้าถึง Container อื่นๆ ทั้งหมดที่อยู่บน Host เดียวกัน รวมถึงข้อมูลสำคัญบน Host ด้วย ตัวอย่างช่องโหว่ที่ทำให้เกิด Container Escape ได้แก่ CVE-2019-5736 ที่เป็นช่องโหว่ใน runc (Container Runtime) ทำให้สามารถ Overwrite runc Binary บน Host ได้ และ CVE-2020-15257 ที่เป็นช่องโหว่ใน containerd ที่อนุญาตให้ Container เข้าถึง Host Network Namespace ได้
สาเหตุหลักที่ทำให้เกิด Container Escape คือการรัน Container ด้วย –privileged Flag ซึ่งจะให้ Container มี Linux Capabilities ทั้งหมด เสมือนรันบน Host โดยตรง การ Mount Docker Socket (/var/run/docker.sock) เข้าไปใน Container ทำให้ Container สามารถสร้าง Container ใหม่บน Host ได้ และการ Mount Host Filesystem เข้าไปใน Container เช่น -v /:/host ทำให้ Container อ่านเขียนไฟล์ทุกอย่างบน Host ได้
Image Vulnerabilities
Container Image ประกอบด้วย Base Image (เช่น Ubuntu, Alpine, Debian) และ Application Layer ที่ Developer เพิ่มเข้าไป Base Image อาจมีช่องโหว่ CVE จำนวนมากจาก Package ที่ติดตั้งมากับ Image ตัวอย่างเช่น Ubuntu Official Image อาจมี Package ที่มี Known Vulnerabilities หลายร้อยรายการ ถ้าไม่ได้ Update เป็นเวอร์ชันล่าสุด นอกจากนี้ Application Dependencies เช่น Python Packages, Node.js Modules หรือ Java Libraries ที่ติดตั้งใน Image ก็อาจมี CVE เช่นกัน ทำให้ Image มี Vulnerabilities สะสมจากทุก Layer
ปัญหาที่พบบ่อยคือการใช้ Image Tag ที่ไม่ Specific เช่น FROM ubuntu:latest ซึ่ง latest Tag อาจชี้ไป Image คนละเวอร์ชันในเวลาที่ต่างกัน ทำให้ Build ไม่ Reproducible และอาจดึง Image ที่มีช่องโหว่ใหม่เข้ามาโดยไม่รู้ตัว ควรใช้ Image Digest แทน เช่น FROM ubuntu@sha256:abc123… เพื่อ Pin ไว้ที่ Image เวอร์ชันที่ทดสอบแล้ว
Misconfiguration
Misconfiguration เป็นปัญหาที่พบบ่อยที่สุดใน Container Environment และมักเป็นช่องทางหลักที่ทำให้เกิด Security Breach ตัวอย่าง Misconfiguration ที่พบบ่อย ได้แก่ การรัน Container ด้วย Root User ซึ่ง Default ของ Docker คือรัน Process ภายใน Container ด้วย Root ทำให้ถ้ามีช่องโหว่ใน Application ผู้โจมตีจะได้ Root Access ภายใน Container ทันที การเปิด Port ที่ไม่จำเป็น ทำให้ Attack Surface ใหญ่ขึ้น การตั้ง Environment Variable ที่มี Secrets เช่น Password หรือ API Key ซึ่งจะถูกบันทึกใน Image Layer และสามารถดึงออกมาได้ง่ายด้วย docker history และการไม่จำกัด Resource (CPU, Memory) ทำให้ Container สามารถใช้ Resource ของ Host จนหมด ทำให้เกิด Denial of Service
Docker Image Hardening: สร้าง Image ที่ปลอดภัย
เลือก Base Image ที่เหมาะสม
การเลือก Base Image เป็นขั้นตอนแรกและสำคัญที่สุดของ Image Hardening เพราะ Base Image คือ Foundation ของทุกอย่างที่จะอยู่ใน Container หลักการสำคัญคือเลือก Base Image ที่มี Package น้อยที่สุดเท่าที่จำเป็น เพื่อลด Attack Surface ให้เล็กที่สุด Base Image ที่แนะนำเรียงตามลำดับความปลอดภัยจากมากไปน้อย ได้แก่
Scratch Image เป็น Image ที่ว่างเปล่าไม่มีอะไรเลย ไม่มี Shell ไม่มี Package Manager ไม่มี Library ใดๆ เหมาะกับ Statically Compiled Binary เช่น Go Application ที่ Compile แบบ Static ได้ ข้อดีคือ Attack Surface เป็นศูนย์ ไม่มีเครื่องมือให้ผู้โจมตีใช้ ข้อเสียคือ Debug ยากมากเพราะไม่มี Shell หรือ Utility ใดๆ
Distroless Image เป็น Image ที่ Google พัฒนาขึ้น มีเฉพาะ Application Runtime (เช่น Java, Python, Node.js) และ Library ที่จำเป็น ไม่มี Shell ไม่มี Package Manager ไม่มี Utility ทั่วไป ทำให้ผู้โจมตีที่เข้าถึง Container ไม่สามารถรัน Shell Command ได้ ตัวอย่างเช่น gcr.io/distroless/java17-debian12 สำหรับ Java Application หรือ gcr.io/distroless/python3-debian12 สำหรับ Python Application
Alpine Linux เป็น Minimal Linux Distribution ที่มีขนาดเพียง 5MB ใช้ musl libc แทน glibc และใช้ BusyBox แทน GNU Utilities ทำให้ Image Size เล็กมากและมี Package น้อย ลด Attack Surface ได้ดี แต่ยังมี Shell และ Package Manager (apk) ให้ใช้ ซึ่งอาจถูกผู้โจมตีใช้ประโยชน์ได้ ข้อควรระวังคือ musl libc อาจมี Compatibility Issue กับ Application บางตัวที่พัฒนาบน glibc
Slim Variant ของ Official Image เช่น python:3.12-slim หรือ node:20-slim เป็นเวอร์ชันที่ตัด Package ที่ไม่จำเป็นออก ทำให้ Image Size เล็กลงและมี Vulnerability น้อยกว่า Full Image แต่ยังมี Package มากกว่า Alpine
Multi-Stage Build
Multi-Stage Build เป็นเทคนิคที่สำคัญที่สุดอย่างหนึ่งในการทำ Image Hardening โดยใช้หลาย FROM Statement ใน Dockerfile เดียว แยก Build Stage ออกจาก Runtime Stage ทำให้ Final Image ไม่มี Build Tools, Source Code หรือ Dependencies ที่ใช้เฉพาะตอน Build
ตัวอย่าง Multi-Stage Build สำหรับ Go Application เริ่มจาก Stage แรกใช้ golang:1.22-alpine เป็น Build Stage เพื่อ Compile Source Code ให้ได้ Binary จากนั้น Stage ที่สองใช้ scratch หรือ gcr.io/distroless/static เป็น Runtime Stage แล้ว COPY –from=builder เอาเฉพาะ Binary ที่ Compile ได้มาใส่ ผลลัพธ์คือ Final Image มีเฉพาะ Binary ไม่มี Go Compiler ไม่มี Source Code ไม่มี Package Manager ทำให้ Image Size เล็กมาก (อาจเหลือแค่ 10-20 MB จาก Original หลายร้อย MB) และ Attack Surface เล็กมาก
สำหรับ Node.js Application ก็ใช้หลักการเดียวกัน Stage แรกใช้ node:20-alpine เพื่อ npm install และ npm run build จากนั้น Stage ที่สองใช้ node:20-alpine อีก Image แต่ COPY เฉพาะ node_modules ที่เป็น Production Dependencies (npm ci –production) และ Build Output มา ไม่เอา devDependencies และ Source Code มาด้วย
Non-Root User
การรัน Container ด้วย Non-Root User เป็น Best Practice ที่สำคัญมาก Default ของ Docker คือรัน Process ด้วย Root User (UID 0) ภายใน Container ถ้าผู้โจมตีสามารถ Exploit ช่องโหว่ใน Application และได้ Shell Access ในฐานะ Root พวกเขาจะมีสิทธิ์ทำอะไรก็ได้ภายใน Container รวมถึงเพิ่มโอกาสในการทำ Container Escape
วิธีการสร้าง Non-Root User ใน Dockerfile ใช้ RUN addgroup –system appgroup && adduser –system –ingroup appgroup appuser เพื่อสร้าง System User ที่ไม่มี Home Directory ไม่มี Login Shell จากนั้นใช้ USER appuser เพื่อสลับให้ Process ที่รันหลังจากนี้ทำงานในฐานะ appuser แทน Root สิ่งสำคัญคือต้องวาง USER Statement หลังจาก RUN Commands ที่ต้องการ Root Permission (เช่น apt-get install หรือ apk add) เพราะ Non-Root User จะไม่สามารถติดตั้ง Package ได้
นอกจากนี้ต้องตรวจสอบว่า Application Files มี Permission ที่ถูกต้อง ให้ appuser อ่านได้แต่ไม่จำเป็นต้องเขียน ใช้ COPY –chown=appuser:appgroup เพื่อ Set Ownership ตั้งแต่ตอน COPY Files เข้า Image
Read-Only Filesystem
การตั้ง Container Filesystem เป็น Read-Only เป็นอีกหนึ่ง Defense-in-Depth Layer ที่สำคัญ ป้องกันไม่ให้ผู้โจมตีเขียนไฟล์ลง Container Filesystem เช่น เขียน Malware Binary เขียน Web Shell หรือแก้ไข Configuration File วิธีการคือใช้ –read-only Flag ตอนรัน Container เช่น docker run –read-only myapp
แต่ Application หลายตัวต้องการเขียนไฟล์ชั่วคราว เช่น /tmp สำหรับ Temporary Files หรือ /var/log สำหรับ Log Files วิธีแก้คือใช้ tmpfs Mount สำหรับ Directory ที่ต้องเขียน เช่น docker run –read-only –tmpfs /tmp:rw,noexec,nosuid –tmpfs /var/log:rw,noexec,nosuid myapp ซึ่ง tmpfs จะเก็บข้อมูลใน Memory ไม่ Persist ลง Disk และ Flag noexec จะป้องกันไม่ให้รัน Binary จาก tmpfs ได้ ส่วน nosuid จะป้องกัน SUID Bit
Dockerfile Best Practices สำหรับ Security
นอกจากหลักการใหญ่ๆ ข้างต้นแล้ว ยังมี Best Practices เล็กๆ น้อยๆ ใน Dockerfile ที่ช่วยเพิ่ม Security ได้อย่างมาก
Pin Package Version ทุกครั้ง เมื่อติดตั้ง Package ด้วย Package Manager ให้ระบุ Version ที่ต้องการเสมอ เช่น RUN apk add –no-cache curl=8.5.0-r0 แทน RUN apk add curl เพื่อป้องกัน Package เวอร์ชันใหม่ที่อาจมี Bug หรือ Vulnerability เข้ามาโดยไม่รู้ตัว
ลบ Cache และ Temporary Files หลังติดตั้ง Package ให้ลบ Package Manager Cache ใน RUN Command เดียวกัน เช่น RUN apt-get update && apt-get install -y –no-install-recommends curl && rm -rf /var/lib/apt/lists/* การรวมหลาย Command ใน RUN เดียวกันด้วย && ทำให้ Cache ถูกลบใน Layer เดียวกัน ไม่เหลือค้างใน Intermediate Layer
ใช้ COPY แทน ADD คำสั่ง ADD มีฟีเจอร์เพิ่มเติมคือสามารถดาวน์โหลดไฟล์จาก URL และ Auto-Extract Archive ได้ ซึ่งอาจเป็น Security Risk เพราะอาจดาวน์โหลดไฟล์ที่ไม่ปลอดภัยหรือ Extract Archive ที่มี Malware ใช้ COPY ซึ่งทำหน้าที่แค่ Copy ไฟล์จาก Build Context เข้า Image เท่านั้น ปลอดภัยกว่า
ใช้ .dockerignore File เพื่อป้องกันไม่ให้ไฟล์ที่ไม่จำเป็นหรือไฟล์ที่มี Sensitive Data ถูก Copy เข้า Build Context ไฟล์ที่ควรอยู่ใน .dockerignore ได้แก่ .git, .env, *.key, *.pem, node_modules, __pycache__, Dockerfile, docker-compose.yml, README.md และ Test Files
ลดจำนวน Layer ด้วยการรวม RUN Commands ที่เกี่ยวข้องเข้าด้วยกัน แต่ละ RUN, COPY, ADD สร้าง Layer ใหม่ Layer ที่มากเกินไปทำให้ Image Size ใหญ่ขึ้นและมี Attack Surface มากขึ้น แต่อย่ารวมมากเกินไปจนอ่านยาก ให้รวมเฉพาะ Commands ที่เกี่ยวข้องกัน
ใช้ HEALTHCHECK เพื่อให้ Docker ตรวจสอบว่า Application ภายใน Container ยังทำงานปกติ HEALTHCHECK –interval=30s –timeout=5s –retries=3 CMD curl -f http://localhost:8080/health || exit 1 ถ้า Health Check ล้มเหลว Docker จะ Mark Container เป็น Unhealthy และ Orchestrator (เช่น Docker Swarm หรือ Kubernetes) จะ Restart Container
Image Scanning: ตรวจหาช่องโหว่ใน Container Image
Trivy
Trivy เป็น Open Source Vulnerability Scanner ที่พัฒนาโดย Aqua Security เป็นเครื่องมือที่ได้รับความนิยมสูงสุดในปี 2026 สำหรับ Container Image Scanning สามารถ Scan ได้หลากหลาย ทั้ง Container Image, Filesystem, Git Repository และ Kubernetes Cluster Trivy สามารถตรวจจับ OS Package Vulnerabilities (เช่น CVE ใน apt, apk packages) Application Dependencies Vulnerabilities (เช่น CVE ใน pip, npm, maven packages) Misconfiguration (เช่น Dockerfile Best Practice Violations) Secrets (เช่น AWS Access Key, Private Key ที่ฝังอยู่ใน Image) และ License Compliance
การใช้ Trivy Scan Container Image ทำได้ง่ายมาก เพียง trivy image myapp:latest จะแสดงรายการ Vulnerabilities ทั้งหมดที่พบ พร้อม Severity Level (CRITICAL, HIGH, MEDIUM, LOW) และ CVE ID สามารถ Filter เฉพาะ Severity ที่สนใจ เช่น trivy image –severity CRITICAL,HIGH myapp:latest และสามารถ Output เป็น JSON เพื่อนำไป Process ต่อ เช่น trivy image -f json -o results.json myapp:latest
Trivy สามารถ Integrate กับ CI/CD Pipeline ได้ง่าย ตัวอย่างใน GitHub Actions สามารถเพิ่ม Step ที่รัน Trivy Scan หลังจาก Build Image และก่อน Push ไป Registry ถ้าพบ CRITICAL Vulnerability จะ Fail Pipeline ไม่ให้ Deploy Image ที่มีช่องโหว่ร้ายแรง
Grype
Grype เป็น Vulnerability Scanner ที่พัฒนาโดย Anchore เป็น Open Source และออกแบบมาให้ทำงานร่วมกับ Syft (SBOM Generator) ของ Anchore Grype สามารถ Scan Container Image และ Filesystem เพื่อหา CVE ในทั้ง OS Packages และ Application Dependencies เช่นเดียวกับ Trivy
จุดเด่นของ Grype คือความเร็วในการ Scan และการทำงานร่วมกับ Syft ที่สามารถสร้าง Software Bill of Materials (SBOM) ในรูปแบบ SPDX หรือ CycloneDX ได้ SBOM เป็นรายการ Components ทั้งหมดที่อยู่ใน Image ทำให้สามารถตรวจสอบ Vulnerability ได้แม้ไม่มี Image อยู่แล้ว เพียงมี SBOM ก็สามารถ Scan ได้
Snyk Container
Snyk Container เป็น Commercial Tool ที่มี Free Tier สำหรับ Open Source Projects สามารถ Scan Container Image หา Vulnerability พร้อมให้คำแนะนำวิธีแก้ไข เช่น แนะนำ Base Image เวอร์ชันที่มี Vulnerability น้อยกว่า หรือแนะนำ Package เวอร์ชันที่ Fix CVE แล้ว Snyk Container มี Integration กับ Container Registry หลายตัว เช่น Docker Hub, ECR, GCR, ACR ทำให้สามารถ Scan Image ที่อยู่ใน Registry ได้โดยตรง
Docker Scout
Docker Scout เป็น Feature ใหม่ที่ Docker พัฒนาขึ้นมาเพื่อให้ Vulnerability Scanning เป็นส่วนหนึ่งของ Docker CLI โดยตรง สามารถใช้ docker scout cves myapp:latest เพื่อ Scan Image หา CVE ได้ทันที Docker Scout มี Integration กับ Docker Desktop และ Docker Hub ทำให้สามารถเห็น Vulnerability Information ได้จาก Docker Hub UI โดยตรง จุดเด่นคือความสะดวกในการใช้งานเพราะเป็นส่วนหนึ่งของ Docker Ecosystem
Trusted Base Images และ Image Signing
Docker Official Images และ Verified Publishers
Docker Hub มีระบบ Verified Publisher และ Official Images เพื่อให้ผู้ใช้สามารถแยกแยะ Image ที่น่าเชื่อถือจาก Image ที่ไม่น่าเชื่อถือ Official Images เป็น Image ที่ Docker สร้างและดูแลเอง หรือร่วมกับ Upstream Project (เช่น python, node, nginx) ผ่าน Docker Official Images Program มีการ Review Dockerfile, Scan Vulnerability เป็นประจำ และ Update ตาม Security Patch อย่างรวดเร็ว ควรใช้ Official Images เป็น Base Image เสมอแทนที่จะใช้ Community Images ที่ไม่รู้ที่มา
Verified Publisher เป็น Image ที่พัฒนาโดยองค์กรที่ Docker ตรวจสอบแล้วว่ามีตัวตนจริง เช่น Image จาก Microsoft, RedHat, Google ทำให้มั่นใจได้ว่า Image ไม่ถูกแทรก Malware จากผู้พัฒนาปลอม
Image Signing ด้วย Cosign
Cosign เป็นเครื่องมือสำหรับ Sign และ Verify Container Image ที่พัฒนาโดย Sigstore Project ซึ่งเป็นส่วนหนึ่งของ Linux Foundation Cosign ช่วยให้สามารถตรวจสอบได้ว่า Image ที่จะ Deploy มาจากแหล่งที่น่าเชื่อถือจริง ไม่ถูกแก้ไขระหว่างทาง
วิธีการใช้ Cosign เริ่มจากสร้าง Key Pair ด้วย cosign generate-key-pair จะได้ cosign.key (Private Key) และ cosign.pub (Public Key) จากนั้น Sign Image ด้วย cosign sign –key cosign.key myregistry/myapp:v1.0 Cosign จะสร้าง Signature และ Push ไปยัง Registry เดียวกับ Image เวลา Verify ใช้ cosign verify –key cosign.pub myregistry/myapp:v1.0 ถ้า Signature ถูกต้อง จะแสดงข้อมูล Signature ถ้า Image ถูกแก้ไขหลังจาก Sign แล้ว Verification จะ Fail
ใน Production ควร Enforce Policy ให้ Deploy ได้เฉพาะ Image ที่ Sign แล้ว โดยใช้ Admission Controller ใน Kubernetes เช่น Kyverno หรือ OPA Gatekeeper ที่ตรวจสอบ Cosign Signature ก่อนอนุญาตให้ Pod ถูกสร้าง
Notary v2 (Notation)
Notary v2 หรือที่เรียกว่า Notation เป็น CNCF Project สำหรับ Container Image Signing ที่ออกแบบมาให้ทำงานร่วมกับ OCI Distribution Spec จุดเด่นคือ Signature ถูกเก็บเป็น OCI Artifact ใน Registry เดียวกับ Image ทำให้ไม่ต้องมี Transparency Log แยก และ Registry ที่รองรับ OCI Spec สามารถเก็บ Signature ได้โดยไม่ต้องแก้ไขอะไร Azure Container Registry, AWS ECR และ Google Artifact Registry รองรับ Notation แล้วในปี 2026
Runtime Security: ป้องกัน Container ที่กำลังรัน
Seccomp Profile
Seccomp (Secure Computing Mode) เป็น Linux Kernel Feature ที่จำกัด System Calls ที่ Process สามารถเรียกใช้ได้ Docker มี Default Seccomp Profile ที่ Block System Calls ประมาณ 44 ตัวที่อันตราย เช่น reboot, mount, ptrace, setns แต่ยังอนุญาต System Calls อีกหลายร้อยตัว
สำหรับ Application ที่รู้ว่าใช้ System Calls อะไรบ้าง สามารถสร้าง Custom Seccomp Profile ที่อนุญาตเฉพาะ System Calls ที่จำเป็น (Allowlist Approach) ลด Attack Surface ได้อย่างมาก สามารถใช้เครื่องมืออย่าง strace หรือ oci-seccomp-bpf-hook เพื่อ Trace ว่า Application ใช้ System Calls อะไรบ้าง แล้วสร้าง Profile จากข้อมูลที่ Trace ได้
ห้ามรัน Container ด้วย –security-opt seccomp=unconfined เด็ดขาดใน Production เพราะจะปิด Seccomp Protection ทั้งหมด ทำให้ Container สามารถเรียก System Calls ทุกตัวได้ รวมถึง System Calls ที่อาจใช้ในการทำ Container Escape
AppArmor
AppArmor เป็น Linux Security Module (LSM) ที่ทำงานแบบ Mandatory Access Control (MAC) ใช้ Profile เพื่อจำกัดว่า Process สามารถเข้าถึง File, Network, Capability อะไรได้บ้าง Docker มี Default AppArmor Profile ชื่อ docker-default ที่ Block การเข้าถึง Filesystem ที่อันตราย เช่น /proc/sysrq-trigger, /sys/firmware และ Block การ Mount Filesystem
สามารถสร้าง Custom AppArmor Profile ที่เข้มงวดกว่า Default ได้ เช่น จำกัดให้ Application อ่านได้เฉพาะ Directory ที่กำหนด เขียนได้เฉพาะ /tmp จำกัด Network Access ให้เชื่อมต่อได้เฉพาะ Port ที่กำหนด AppArmor Profile ต้องโหลดบน Host ก่อน แล้วระบุตอนรัน Container ด้วย –security-opt apparmor=my-custom-profile
SELinux
SELinux (Security-Enhanced Linux) เป็น Linux Security Module อีกตัวที่ทำ Mandatory Access Control ใช้ Label-Based Access Control ที่ทุก Process, File, Port จะมี SELinux Label และ Policy จะกำหนดว่า Process ที่มี Label นี้สามารถเข้าถึง File ที่มี Label นั้นได้หรือไม่ SELinux เป็นค่า Default บน RHEL, CentOS, Fedora และ AlmaLinux
Docker บน SELinux-enabled Host จะรัน Container ด้วย SELinux Label svirt_lxc_net_t โดย Default ซึ่งจำกัดการเข้าถึง Host Filesystem และ Container อื่น ปัญหาที่พบบ่อยคือ Developer ปิด SELinux (setenforce 0) เพราะ Application ไม่ทำงาน แทนที่จะแก้ Policy ให้ถูกต้อง การปิด SELinux เป็นเรื่องอันตรายมากใน Production
Linux Capabilities
Linux Capabilities แบ่ง Root Privilege ออกเป็นชิ้นเล็กๆ (ประมาณ 40 Capabilities) แทนที่จะให้ All-or-Nothing Root Access Docker จะ Drop Capabilities หลายตัวโดย Default เมื่อรัน Container เช่น CAP_SYS_ADMIN, CAP_NET_ADMIN แต่ยังคง Capabilities บางตัวไว้ เช่น CAP_CHOWN, CAP_SETUID
Best Practice คือ Drop All Capabilities แล้วเพิ่มเฉพาะที่จำเป็น เช่น docker run –cap-drop ALL –cap-add NET_BIND_SERVICE myapp จะลบ Capabilities ทั้งหมด แล้วเพิ่มเฉพาะ NET_BIND_SERVICE ที่อนุญาตให้ Bind Port ต่ำกว่า 1024 ได้ ห้ามใช้ –cap-add ALL หรือ –privileged เด็ดขาดใน Production
Docker Daemon Security
Docker Daemon (dockerd) เป็น Background Process ที่จัดการ Container ทั้งหมด รันด้วย Root Privilege บน Host ดังนั้น Security ของ Docker Daemon จึงสำคัญมาก ถ้าผู้โจมตีสามารถเข้าถึง Docker Daemon ได้ เท่ากับมี Root Access บน Host
Docker Daemon Configuration ที่ควรตั้ง ได้แก่ เปิดใช้งาน Content Trust (DOCKER_CONTENT_TRUST=1) เพื่อให้ Docker ตรวจสอบ Signature ของ Image ก่อน Pull เปิดใช้งาน User Namespace Remapping เพื่อให้ Root ภายใน Container ถูก Map เป็น Non-Root บน Host ลดผลกระทบของ Container Escape ตั้ง Default Ulimits เพื่อจำกัด Resource ที่ Container ใช้ได้ เปิดใช้งาน Live Restore เพื่อให้ Container ยังรันอยู่ได้แม้ Docker Daemon Restart และตั้ง Log Driver เป็น json-file พร้อม Max Size และ Max File เพื่อป้องกัน Log เต็ม Disk
การตั้งค่าเหล่านี้สามารถกำหนดใน /etc/docker/daemon.json ได้ เช่น การตั้ง userns-remap เป็น default จะทำให้ Docker สร้าง dockremap User และ Map UID ภายใน Container เป็น UID ที่ไม่มี Privilege บน Host โดยอัตโนมัติ
Docker Socket Protection
Docker Socket (/var/run/docker.sock) เป็น Unix Socket ที่ Docker CLI ใช้สื่อสารกับ Docker Daemon ใครก็ตามที่เข้าถึง Docker Socket ได้ จะสามารถควบคุม Docker Daemon ได้ทั้งหมด รวมถึงสร้าง Privileged Container ที่เข้าถึง Host Filesystem ได้ ดังนั้นการ Mount Docker Socket เข้าไปใน Container (-v /var/run/docker.sock:/var/run/docker.sock) เป็นเรื่องอันตรายมาก เพราะ Process ภายใน Container จะสามารถควบคุม Docker Daemon บน Host ได้
ทางเลือกที่ปลอดภัยกว่าสำหรับ Use Case ที่ต้องการ Docker-in-Docker ได้แก่ใช้ Kaniko สำหรับ Build Image ภายใน Container โดยไม่ต้อง Docker Daemon ใช้ Buildah สำหรับ Build OCI Image โดยไม่ต้อง Docker Daemon ใช้ Docker Socket Proxy เช่น Tecnativa docker-socket-proxy ที่เป็น Reverse Proxy สำหรับ Docker Socket ทำให้สามารถจำกัดว่า Container เข้าถึง Docker API อะไรได้บ้าง หรือใช้ Rootless Docker ที่รัน Docker Daemon ด้วย Non-Root User ทำให้แม้ Docker Socket ถูก Compromise ผู้โจมตีก็จะไม่ได้ Root Access บน Host
Container Registry Security
Harbor Registry
Harbor เป็น Open Source Container Registry ที่พัฒนาโดย VMware (ปัจจุบันเป็น CNCF Graduated Project) ออกแบบมาสำหรับ Enterprise ที่ต้องการ Private Container Registry ที่มี Security Features ครบถ้วน
Security Features ของ Harbor ได้แก่ Vulnerability Scanning แบบ Built-in โดย Integrate กับ Trivy เป็น Default Scanner สามารถตั้ง Policy ให้ Block Image ที่มี CRITICAL Vulnerability ไม่ให้ Pull ได้ Image Signing ด้วย Cosign หรือ Notary เพื่อ Verify Image Authenticity Role-Based Access Control (RBAC) เพื่อจำกัดว่า User ใดสามารถ Push/Pull Image ใน Repository ใดได้ Replication เพื่อ Replicate Image ไปยัง Registry อื่น เช่น Replicate จาก On-Premises Registry ไปยัง Cloud Registry Image Retention Policy เพื่อลบ Image เก่าโดยอัตโนมัติ ลด Storage Cost และ Garbage Collection เพื่อลบ Layer ที่ไม่มี Image ใช้แล้ว
นอกจาก Harbor แล้ว Cloud Providers ทุกรายก็มี Managed Container Registry ที่มี Security Features เช่น AWS ECR มี Image Scanning ด้วย Inspector, Google Artifact Registry มี Vulnerability Scanning ด้วย Container Analysis, Azure Container Registry มี Microsoft Defender for Containers
Kubernetes-Specific Container Security
Pod Security Admission (PSA)
Pod Security Admission เป็น Built-in Admission Controller ใน Kubernetes ตั้งแต่ v1.25 ใช้แทน PodSecurityPolicy ที่ถูก Deprecate แล้ว PSA กำหนด 3 Security Levels ได้แก่ Privileged ที่ไม่มีข้อจำกัด เหมาะกับ System-Level Workloads เช่น CNI Plugin, Log Collector Baseline ที่ป้องกัน Known Privilege Escalation Paths เช่น ห้ามใช้ hostNetwork, hostPID, hostIPC ห้ามรัน Container แบบ Privileged ห้ามเพิ่ม Capabilities ที่อันตราย และ Restricted ที่เข้มงวดที่สุด บังคับใช้ Best Practices ทั้งหมด เช่น ต้องรัน Non-Root ต้อง Drop ALL Capabilities ต้องไม่ Mount Host Path
PSA ถูก Apply ในระดับ Namespace โดยใช้ Label เช่น pod-security.kubernetes.io/enforce: restricted จะทำให้ทุก Pod ที่สร้างใน Namespace นี้ต้องผ่าน Restricted Policy ถ้าไม่ผ่าน Pod จะถูก Reject ไม่ให้สร้าง สามารถใช้ Mode ที่แตกต่างกัน ได้แก่ enforce ที่ Block Pod ที่ไม่ผ่าน audit ที่ Log Warning แต่ไม่ Block และ warn ที่แสดง Warning Message ให้ User
RuntimeClass
RuntimeClass เป็น Kubernetes Resource ที่ใช้เลือก Container Runtime สำหรับ Pod ทำให้สามารถรัน Pod ที่ต้องการ Security สูงด้วย Sandboxed Runtime เช่น gVisor หรือ Kata Containers แทน Default Runtime (เช่น runc)
gVisor เป็น User-Space Kernel ที่ Intercept System Calls จาก Container และจัดการเอง ไม่ส่งไปยัง Host Kernel โดยตรง ทำให้แม้มีช่องโหว่ใน Container Application ผู้โจมตีก็ไม่สามารถ Exploit Host Kernel ได้ เหมาะกับ Workloads ที่ไม่น่าเชื่อถือ เช่น Untrusted Code Execution
Kata Containers รัน Container ภายใน Lightweight Virtual Machine แยก Kernel จาก Host อย่างสมบูรณ์ ให้ Security Level เทียบเท่า VM แต่มี Performance Overhead มากกว่า gVisor
Secrets Management ใน Container
การจัดการ Secrets (เช่น Database Password, API Key, TLS Certificate) เป็นเรื่องสำคัญมากใน Container Environment กฎข้อแรกคือ ห้ามใส่ Secrets ใน ENV ของ Dockerfile เด็ดขาด เพราะ Environment Variable จะถูกบันทึกใน Image Layer สามารถดึงออกมาได้ด้วย docker inspect หรือ docker history และใครก็ตามที่เข้าถึง Image ได้จะเห็น Secrets ทั้งหมด
วิธีที่ถูกต้องในการจัดการ Secrets ใน Container ได้แก่ ใช้ Docker Secrets (สำหรับ Docker Swarm) ที่ Mount Secrets เป็นไฟล์ใน /run/secrets/ ภายใน Container Secrets ถูกเข้ารหัสระหว่าง Transit และ At Rest ใช้ Kubernetes Secrets ที่เก็บ Secrets ใน etcd (ควรเปิดใช้ Encryption at Rest) และ Mount เป็น Volume หรือ Environment Variable ให้ Pod แต่ Kubernetes Secrets เป็น Base64 Encoded ไม่ได้เข้ารหัส ดังนั้นควรใช้ร่วมกับ External Secrets Operator
ใช้ External Secret Management เช่น HashiCorp Vault, AWS Secrets Manager, Azure Key Vault หรือ Google Secret Manager ที่มี Features อย่าง Encryption, Access Control, Audit Logging และ Secret Rotation ใน Kubernetes ใช้ External Secrets Operator หรือ Vault CSI Provider เพื่อ Sync Secrets จาก External Source มาเป็น Kubernetes Secrets โดยอัตโนมัติ
ห้ามใส่ Secrets ใน Docker Build Args (–build-arg) เช่นกัน เพราะ Build Args ถูกบันทึกใน Image History สำหรับ Build Time Secrets (เช่น Private Repository Credential ที่ต้องใช้ตอน npm install) ใช้ Docker BuildKit Secret Mount แทน เช่น RUN –mount=type=secret,id=npmrc,target=/root/.npmrc npm install ซึ่ง Secret จะถูกใช้เฉพาะตอน Build ไม่ถูกบันทึกใน Image Layer
Container Networking Security
Default ของ Docker คือ Container ทุกตัวที่อยู่บน Bridge Network เดียวกันสามารถสื่อสารกันได้ทั้งหมด ซึ่งไม่ปลอดภัยเพราะถ้า Container หนึ่งถูก Compromise ผู้โจมตีจะสามารถเข้าถึง Container อื่นๆ บน Network เดียวกันได้ทันที
Best Practices สำหรับ Container Networking Security ได้แก่ สร้าง Custom Bridge Network แยกสำหรับแต่ละ Application Stack เช่น Frontend Network, Backend Network, Database Network ทำให้ Container ที่ไม่เกี่ยวข้องกันไม่สามารถสื่อสารกันได้ ปิด Inter-Container Communication (ICC) บน Bridge Network ที่ไม่ต้องการ โดยใช้ –icc=false ใน Docker Daemon Configuration ใช้ Docker Network Alias แทน Link เพราะ Link เป็น Legacy Feature ที่ไม่ปลอดภัย
ใน Kubernetes ใช้ Network Policy เพื่อจำกัด Traffic ระหว่าง Pod Default ของ Kubernetes คือทุก Pod สื่อสารกันได้ (Allow All) ควรเริ่มจาก Default Deny Policy ที่ Block Traffic ทั้งหมด แล้วค่อยสร้าง Policy อนุญาตเฉพาะ Traffic ที่จำเป็น (Allowlist Approach) ตัวอย่างเช่น อนุญาตเฉพาะ Frontend Pod ให้เชื่อมต่อ Backend Pod บน Port 8080 และอนุญาตเฉพาะ Backend Pod ให้เชื่อมต่อ Database Pod บน Port 5432
Network Policy ต้องใช้ CNI Plugin ที่รองรับ เช่น Calico, Cilium, Weave Net ไม่ใช่ทุก CNI Plugin จะรองรับ Network Policy เช่น Flannel ไม่รองรับ Cilium มีความสามารถเพิ่มเติมคือ Layer 7 Network Policy ที่สามารถจำกัด Traffic ตาม HTTP Method, Path หรือ Header ได้ ทำให้ Granularity สูงกว่า Default Network Policy ที่ทำได้แค่ Layer 3/4
Monitoring Container Behavior ด้วย Falco
Falco เป็น CNCF Graduated Project ที่ออกแบบมาสำหรับ Runtime Security Monitoring ใน Container และ Kubernetes Environment Falco ทำงานโดย Monitor System Calls ของ Container แบบ Real-Time และ Match กับ Rules ที่กำหนดไว้ เมื่อพบ Behavior ที่ผิดปกติหรือต้องสงสัย Falco จะสร้าง Alert
ตัวอย่าง Built-in Rules ของ Falco ที่ช่วยตรวจจับ Suspicious Activity ได้แก่ ตรวจจับเมื่อมี Shell ถูก Spawn ภายใน Container ซึ่งอาจบ่งบอกว่าผู้โจมตีได้ Shell Access แล้ว ตรวจจับเมื่อมีการอ่าน Sensitive Files เช่น /etc/shadow, /etc/passwd ภายใน Container ตรวจจับเมื่อมี Binary ที่ไม่อยู่ใน Image ถูกรันภายใน Container ซึ่งอาจเป็น Malware ที่ถูกดาวน์โหลดมา ตรวจจับเมื่อมี Network Connection ไปยัง IP ที่ต้องสงสัยหรือ Port ที่ผิดปกติ และตรวจจับเมื่อมีการเปลี่ยนแปลง Namespace ซึ่งอาจเป็นการพยายามทำ Container Escape
Falco สามารถ Integrate กับระบบ Alert หลายตัว เช่น Slack, PagerDuty, Email, Webhook, SIEM (เช่น Splunk, ELK Stack) และใน Kubernetes สามารถ Deploy เป็น DaemonSet เพื่อรัน Falco บนทุก Node โดยอัตโนมัติ Falco ยังมี Falcosidekick ที่เป็น Event Forwarder สามารถส่ง Alert ไปยัง Destination มากกว่า 50 แห่ง
Supply Chain Security (SLSA)
Supply Chain Levels for Software Artifacts (SLSA อ่านว่า “salsa”) เป็น Security Framework ที่ Google พัฒนาขึ้นเพื่อป้องกัน Supply Chain Attack กำหนด 4 Levels ของ Supply Chain Security ได้แก่
SLSA Level 1 (Build) กำหนดว่า Build Process ต้อง Documented และ Automated มี Build Provenance ที่บอกว่า Artifact ถูก Build อย่างไร ที่ไหน จาก Source Code อะไร เป้าหมายคือให้ Trace ได้ว่า Artifact มาจากไหน
SLSA Level 2 (Build Platform) กำหนดว่า Build Process ต้องรันบน Hosted Build Service (เช่น GitHub Actions, GitLab CI, Cloud Build) ไม่ใช่ Developer Machine เพื่อป้องกัน Developer Machine ที่ถูก Compromise ใส่ Malware เข้าไปใน Build Build Provenance ต้อง Signed เพื่อป้องกันการ Tamper
SLSA Level 3 (Build Security) กำหนดว่า Build Process ต้อง Hardened เช่น Build ใน Isolated Environment ไม่มี Developer Access ระหว่าง Build Source Code และ Build Configuration ต้อง Verified ว่ามาจาก Version Control System จริง
SLSA Level 4 (Dependencies) กำหนดว่า Dependencies ทั้งหมดต้องมี Provenance ที่ Verified ได้ ทุก Dependency ต้อง Reviewed เป็น Level ที่เข้มงวดที่สุดและยากที่สุดในการบรรลุ
ในปี 2026 ควรเริ่มจาก SLSA Level 2 เป็นอย่างน้อย โดยใช้ CI/CD Pipeline (เช่น GitHub Actions) ในการ Build Image สร้าง Build Provenance ด้วย SLSA GitHub Generator และ Sign Image ด้วย Cosign
CIS Docker Benchmark
CIS Docker Benchmark เป็น Security Configuration Guide ที่พัฒนาโดย Center for Internet Security (CIS) เป็นมาตรฐานที่ได้รับการยอมรับอย่างกว้างขวางสำหรับ Docker Security ประกอบด้วยคำแนะนำมากกว่า 100 ข้อที่ครอบคลุมทุกแง่มุมของ Docker Security
CIS Docker Benchmark แบ่งเป็นหมวดหมู่หลักดังนี้ Host Configuration ที่ครอบคลุมการ Harden Host OS เช่น ใช้ Dedicated Host สำหรับ Docker อัปเดต Docker Engine เป็นเวอร์ชันล่าสุด ใช้ Separate Partition สำหรับ Docker Data Directory Docker Daemon Configuration ที่ครอบคลุมการตั้งค่า Daemon เช่น ไม่เปิด Docker Daemon API บน Network โดยไม่มี TLS เปิดใช้ Content Trust ตั้ง Default Ulimits Docker Daemon Configuration Files ที่ตรวจสอบ Permission ของ Docker Configuration Files เช่น /etc/docker/daemon.json Container Images and Build File ที่ครอบคลุม Image Security เช่น ใช้ Trusted Base Image สร้าง Non-Root User ใน Image ไม่ใส่ Secrets ใน Dockerfile Container Runtime ที่ครอบคลุม Runtime Security เช่น ไม่รัน Container ด้วย –privileged ไม่ Mount Docker Socket จำกัด Resource Docker Security Operations ที่ครอบคลุมการจัดการ Security ทั่วไป เช่น Image Scanning Security Monitoring Incident Response และ Docker Swarm Configuration สำหรับ Environment ที่ใช้ Docker Swarm
สามารถใช้เครื่องมืออย่าง Docker Bench for Security (docker/docker-bench-security) เพื่อ Automate การตรวจสอบ CIS Docker Benchmark ได้ เครื่องมือนี้จะ Scan Docker Host และแสดง Pass/Fail สำหรับแต่ละ Recommendation พร้อมคำแนะนำวิธีแก้ไข
สรุป: Container Security Checklist 2026
Container Security ไม่ใช่เรื่องที่ทำครั้งเดียวแล้วจบ แต่เป็น Continuous Process ที่ต้องทำตลอด Container Lifecycle ตั้งแต่ Build, Ship ไปจนถึง Run สรุป Checklist ที่ควรทำสำหรับ Container Security ในปี 2026
Build Phase ได้แก่ ใช้ Minimal Base Image (Distroless, Alpine, Scratch), ใช้ Multi-Stage Build, สร้าง Non-Root User, Pin Package Versions, ใช้ .dockerignore, ไม่ใส่ Secrets ใน Image, Scan Image ด้วย Trivy/Grype ก่อน Push, Sign Image ด้วย Cosign
Ship Phase ได้แก่ ใช้ Private Registry (Harbor), ตั้ง Vulnerability Policy บน Registry, Verify Image Signature ก่อน Deploy, สร้าง SBOM สำหรับทุก Image, Automate ทุกอย่างผ่าน CI/CD Pipeline
Run Phase ได้แก่ ใช้ Read-Only Filesystem, Drop All Capabilities แล้วเพิ่มเฉพาะที่จำเป็น, ใช้ Custom Seccomp/AppArmor Profile, ไม่รัน Privileged Container, ไม่ Mount Docker Socket, จำกัด Resource (CPU/Memory Limits), ใช้ Network Policy จำกัด Traffic, ใช้ Secrets Management Tool, Monitor ด้วย Falco, รัน CIS Docker Benchmark เป็นประจำ
การทำ Container Security อย่างครบถ้วนอาจดูเหมือนมีงานมาก แต่เครื่องมือ Open Source ที่มีในปี 2026 ทำให้สามารถ Automate ได้เกือบทุกอย่าง ลงทุนเวลาตั้ง Pipeline ที่ดีครั้งเดียว แล้วจะได้ Container Environment ที่ปลอดภัยในระยะยาว