สำหรับ Week มองว่าการทบทวนเรื่อง Container ของตัวผมเอง ใช้งานมาระดับนึง มีเรื่องที่รู้ และไม่รู้ด้วย ตาม Style การเรียนของผม แบบลักจำมาจากงาน Meetup ครับ มาลองดูสรุปสำหรับสัปดาห์นี้กันครับ
Table of Contents
1. Why Container?
ก่อนที่เราจะรู้ว่าทำไมถึงต้องใช้ Container ต้องมา Recap กันก่อน ว่าเมื่อก่อนเอา Software ไปติดตั้งที่อื่นกันยังไงครับ จาก Code > Build > Executable File เจ้าตัว Executable File มาห่อเป็น Software Package เอาติดตั้ง
ยุคต่างๆของการติดตั้ง Software Package เล่าไว้หน่อยเผื่อน้องๆจบใหม่อ่าน โผล่เข้ามายุค Container เลย โดยมี 3 ยุค
- Bare Metal - กว่าจะมาลง Software Package ได้ ต้องมาสนใจพวก OS / Runtime / Network / Permission / Dependency ต่างๆ (Package อาจจะ Require เช่น Lib สำหรับต่อ DB) เป็นต้น
- ถ้าอะไรพังตัวใคร ตัวมัน ลงใหม่ - Virtual Machine - รวมตัว Bare Metal ห่อไว้เป็นไฟล์ เวลาจะทำอะไร จะได้สะดวกขึ้น ไม่ต้องกังวลว่าแก้แล้วจะพัง Rollback ได้
- การใข้ VM ใช้ตัว Resource ได้ไม่เต็มที่นัก - Container - หาดูจากภาพแล้วจะพบว่า Layer ของ Virtual Machine ยังมี overhead ในส่วนการใช้ Resource จากตัว Hypervisor ตัว Container เลยเข้ามาเติมเต็มใช้ Resource ให้คุ้มๆ
Note: Magic ที่ช่วยให้ Container มีอิสระ (Isolation) โดย key ที่ทำให้ Container เกิดขึ้นมา เนื่องจากตัว Linux Kernel มีตัว C-Group / Namespace ขึ้น
Ref:
- What Are Namespaces and cgroups, and How Do They Work? - NGINX
- Understanding Linux Namespace Types | by Luis Soares | Medium
2. Containers Basics
- Docker Architecture

รูปแบบการทำงานของ Docker จะเป็นตัว Client-Server โดยมีส่วนประกอบที่สำคัญ ดังนี้
- docker Client (docker cli) - program ที่ให้ผู้ใช้ป้อน docker command เพื่อจัดการ Docker Deamon
- Docker Host (เครื่องที่ลง docker)
- Docker Deamon (dockerd) - เป็น Process ที่จัดการ Request มาจาก docker cli เช่น
1. ดึง Image จาก Container Registry ถ้าไม่มี
2. สั่งให้ Image ทำงานเป็น Container เป็นต้น
- Image - พื้นที่ Local ที่เก็บ Image
Note: Image Software Package ที่รวม OS / Runtime / App ที่เบากว่า VM
- Container - Image ที่ถูกใช้งานแล้ว - Container Registry - ที่เก็บ Image / Plugins / Extensions ส่วนกลาง ที่มาแชร์ใช้งานร่วมกัน ปกติจะเป็น hub.docker.com
- พวก Image / Plugins / Extensions Explore Docker's Container Image Repository | Docker Hub
- Docker Command
- docker run - สั่งให้ Image ทำงานเป็น Container ตาม Config ที่กำหนด
- d ให้ทำงานแบบ background mode
- p <host>:<container port> กำหนด port ที่ใช้เชื่อมต่อจากภายนอก
docker run -d -p 8090:80 inv-api-image
- docker stop - หยุดการทำงานของ Container โดยที่ตัว App ทำงานจัดการ State เรียบร้อย (Graceful shutdown)
- docker kill - force shutdown container / data ระหว่างนั้นหาย ใช้กรณีที่เกิด Infinite Loop
- docker pause / docker unpause - หยุดการทำงาน / และให้ทำงานต่อ โดยที่ตัว Container ยัง Hold Resource อยู่
แบบลึกๆดูจากนี้เลย restart - pause vs stop in docker - Stack Overflow - docker start - เปิด Container ทำงาน
- docker images - ตรวจสอบ imageที่อยู่ใน Docker Host
- docker ps / docker ps -a : แสดง Container ที่มี ถ้า -a แสดงทั้งหมด
- docker rm <<container id / container name>> : ลบ Container
- docker rmi <<image id / image name>> : ลบ Image
- docker exec -it <<container id / container name>> <<shell type>> : เข้าไปใน Container จัดการ
docker exec -it inv-api sh docker exec -it inv-api bash
สำหรับคำสั่งอื่นๆดูเพิ่มได้จาก https://docs.docker.com/engine/reference/run/
3. Build Containers
Dockerfile - ไฟล์ที่เก็บ Step การสร้าง Container Image ขึ้นมา ไม่ว่าจะ Run กี่รอบจะได้ผลลัพธ์เหมือนเดิม โดยใน Dockerfile แยกออกเป็น 2 ส่วน
- BUILD TIME - มี Keyword ยังนี้
- FROM บอกว่าจะเอา Base Image มาจากไหน
- WORKDIR กำหนด Directory ปัจจบุัน เพื่อทำงาน อารมร์แบบ CD
- COPY - เอาไฟล์จาก Context มาใส่ที่ Image
- ADD - เอาไฟล์จาก Context มาใส่ที่ Image เหมือนกัน แต่ไม่แนะนำ เพราะมี issue security ถ้ามี zip มันจะแตกออกมาเลย
- RUN - Run Linux Command ตามแต่ละ Distro เลย
- LABEL <KEY>:<VALUE> ใส่ Information ของ Image - RUN TIME - มี Keyword ยังนี้
- EXPOSE บอก port ที่จะให้เปิดออก
- ENTRYPOINT
- CMD
เมื่อได้ Dockerfile ไฟล์มาแล้ว การแปลงาก Dockerfile เป็น Container Image จะใช้คำสั่ง docker build มี Pattern ประมาณนี้
docker build -t <Container_name:Tag_version> --no-cache <context>
- -t บอกชื่อ Image มี 2 แบบ Container_name หรือ Container_name : Tag_version
- Context บอกว่า File สำหรับที่ใช้ Build (พวก Dockerfile) อยู่ที่ไหน ปกติใส่ . หรือ ถ้า Custom File -f <Your_DockerFile>
docker build -t inv-api:1.0.0 . docker build -t inv-api:1.0.0 -f abc.DockerFile docker build -t inv-api:1.0.0 --no-cache -f abc.DockerFile
- --no-cache บอกว่าระหว่าง build ไม่ต้องให้ใช้ cache มันจะช่วยแก้ปัญหาตอน build แล้ว App ยังทำงานเหมือนเดิมได้ ปกติถ้าไม่ใส่ --no-cache ตอนสั่ง build ติดกันถี่ๆ มันจะขึ้นคำว่า CACHE

นอกจาก docker build แล้วมีตัวใหม่อย่าง docker buildx
- ถ้าไม่ต้องการไฟล์อะไรใช้เข้าไปใน Container ให้ใช้ตัว .dockerignore
4. Publish Container
จากข้อ 3 ตอนนี้ image ของเราจะอยู่ในเครื่องของเราเท่านั้น หากจะเอาไปให้คนอื่น หรือคนในทีมใช้งาน ต้องให้ Container Registry มาใช้ จะเป็นของ docker / aws / azure / gcp หรือ ทำ local ใช้เองก็ได้ โดยคำสั่งที่เกี่ยวข้องกับการ Push จะมี
- docker login - เข้า Container Registry
docker login -u <your_username>
- docker tag - กำหนดเวอร์ชันของ image ที่คนอ่านเข้าใจ ปกติ image มันจะมี hash ของมันอยู่แล้ว
ปล. ถ้าใช้ docker build มันจะ tag มาให้อยู่แล้ว - docker push - เอา Container Image ขึ้นไป Public Registry
docker pull <<docker_username>>/inv-api //เจ้าอื่นๆ docker tag inv-api <<YourRegisry>>.azurecr.io/<<YourNameSpace>>/inv-api docker pull dsregistry.azurecr.io/dsnamespace/inv-api
5. Base Image
ใน docker มี image หลายแบบ โดยแบบที่เราควรรู้จัก มีดังนี้
- scratch - Base Image ตัวแรกเลย
- Official Image - Image ที่มาจากผู้ผลิตที่น่าเชื่อถือ มี Best Practice มาระดับนึง โดยจะมี Official Doc ชัดเจน และรูปแบบการ Support ชัดเจน
- Long Term Support
- Extended Long Term Support
โดยถ้าเราดูใน docker hub จะมีหลายชื่อเลย มีตัวที่ต้องสนใจ
- debian - Project แม่ของ Ubuntu โดยมี Codename ให้จดจำ เช่น bookworm / bulleye
- -slim - docker image ที่ตัด lib บางตัวให้เล็กลง debian > debian-slim
- -alpine - OS ขนาดเล็ก สำหรับ Container
- windowsservercore - สำหรับ Deploy Legacy App อย่าง .NET Framework ที่ไป Linux ไม่ได้
เราจะเลือก Base Image ยังไง ?
- size - deploy ไว
- debian มี apt เป็น package manager
- alpine ใช้ musl libc จะมี apk เป็น package manager - Official Image
- ระยะเวลา Support ควรเป็น Long Term Support
- Update ล่าสุดของ Image
- ในแง่ Security อาจจะต้องเข้าไปดูแต่ละ Layer ว่ายัดอะไรมาบ้าง
6. single stage vs multi-stage
จากหัวข้อที่ 5 ตอนนี้ เราจะทำ Image เป็น Single Stage Build แต่ทว่า มันอาจจะมีขนาดที่ใหญ่เกิดไป เลยต้องแยกออกมาเป็น Multi-Stage แทน เพื่อตัดของที่ไม่จำเป็นไป อยากเข้าตอน Build App เราอยากได้แค่ผลลัพธ์ ส่วน Temp / Dependency สำหรับ Build เราไม่ได้ใช้

อันนี้มี Blog ส่วนตัวผมที่เขียนเรื่อง Multi-Stage และการลดขนาดของ Container ลองมาดูได้เลยครับ
7. Container Security
การทำงานของ Docker มันจะให้ Kernel ร่วมกับ Host น่าจะเรียกว่าเป็น Userspace ถ้าคุมสิทธิได้ไม่ดี อาจจะเกิดการแก้ไข Container B จาก A หรือ กระโดดไปใช้สิทธิของ Host
- privilege escalation - ยกระดับสิทธิ
- ป้องกัน ใน Container ให้ใช้ non-root user ในการทำงานแทน Container
- ป้องกัน rootless จากใน Container และยังให้ non-root user start container ที่ host - surface attack - Image ที่อยู่ใน Public Registry อาจจะมีผู้ไม่ประสงค์ดี ยัด malicious software ลงไป เพื่อให้คนเข้าไปใช้งาน
- ป้องกัน distroless image - โดย Google ไม่มี shell ก็ลำบาก มีตัว Runtime / App ถ้าจะ shell ใช้ sidecar มาช่วย
- ป้องกัน UBI image - ของ RedHat Shell ยังมีอยู่นะ แต่ทว่าบางคำสั่งตัดออกไป เช่น พวก yum
4C Container Security ที่ต้องสนใจ
- Code
- Container
- Cluster ตัว Container Runtime / App
- Cloud
Ref: Overview of Cloud Native Security | Kubernetes
8. Container Orchestration Fundamental
ตอนนี้มีเรื่อง Container แต่พอมันมีเยอะๆเข้า เราต้องมามีประเด็นที่ต้องมาติดกันต่อ ดังนี้
- สามารถจัดการ Resource พวก CPU / Memory / Network ที่ Container แต่ละตัวต้องการได้
- กำหนดให้ Container ใช้ประสิทธิภาพได้สูงสุด
- ดูแลให้ตัว Container มีความพร้อมใช้งาน (availability)
- ถ้าตัว Container ตายขึ้นมา ต้องสร้างขึ้นมาทดแทนได้ แต่ต้อง Design ให้ Container เป็น Stateless ด้วย
- ถ้า Load เข้ามาเยอะๆ พร้อม Scale - จัดการ Network ถ้าให้ Manual ทำไม่น่าจะไหว
- จัดการ Storage ของ Container เพราะแยก Stateless แล้วต้องมาเผื่อที่จัดเก็บ
จากประเด็นข้างต้น ตัว Container Orchestration มีตัว
- control plane - management of the containers
- worker nodes - ตัวที่ให้ containers มัน deploy และทำงาน
Container Orchestration ที่ดังๆ K8S / Docker Swarm
9. Networking
- มีมาตรฐานการอย่าง containernetworking/cni: Container Network Interface - networking for Linux containers (github.com) ดังนั้นไม่ว่าจะใช้ Network แบบไหน easy to swap out different plugins
- ปกติ Network ของ Container docker จะ
- None Network - ไม่ต่อกับใครเลย / Host เข้าไม่ได้
- Host Network - ใช้ Network ของ Host เลย
- Bridge Network - มีตัว Bridge Driver มาครอบอีกที ช่วยให้ Container คุยกันเองได้ (intercontainer) ถ้าอยู่เครื่องเดียวกัน
- Overlay Network - Bridge ขนาดใหญ่ ใช้ Docker Engine หลายตัว Overlay network driver | Docker Docs
10. Service Discovery & DNS
เวลา Container จะให้มาคุยกัน ด้วย IP ใครจะไปจำไหว มีหลาย DC / Region ดังนั้นเลยต้องเอา Automation ช่วย
- Service Registry - ลงทะเบียนตอน Container เกิดใหม้ เข้าระบบ
- Service Discovery - มาหาตามที่ลงทะเบียนไว้
แนวคิดที่ช่วยให้ Service Discovery / Service Registry สำเร็จมี 2 วิธี
- DNS
- Key-Value Store พวก etcd/ Consul / Apache Zookeeper / Raft
11. Service Mesh
Service Mesh - เป็น Layer อีกอันนึงที่ช่วยครอบ Container ในรูปแบบของ Side Car Proxy ที่เข้ามาช่วยจัดการการสื่อสารของแต่ละ Container โดยเข้า Filter Traffic / Load Balancing เป็นต้น
และพอใช้ Side Car บาง Pattern อย่าง Timeout / Retry / Circuit Breakers ไม่ต้องมาเขียน Code เพิ่มคุมจาก Proxy ตัว Tools nginx, HAProxy, Envoy, Istio

12. Storage
จำได้ว่า Container เป็น Stateless ได้ใช่ปะ ดังนั้นตัว Container ต้องมี Storage แยกอีก Layer ออกมา เพื่อเก็บข้อมูล มี 2 แบบ
- mount
- volume

สำหรับกิจกรรม Onsite วันนี้สนุกมาก ได้คิดเยอะด้วย ทำให้ปลอดภัย มันง่ายกว่าทำให้เล็กลง 555 นั่งคิดนานมาก สุดท้ายได้ Hint Multi-Stage เลยไปนึกจาก Blog ทำให้ตัว ICONV support TIS-620 ที่ Build เตรียมไว้ แล้วเอามาแปะใส่ (กลับไปยังคาใจเลยไปโมเพิ่มมา 55) และตอนเย็นมีจับกลุ่มเตรียมทำ Senior Project ผมคงต้องไปรื้่อ Skill Coding เหมือนกัน จับ C# Logic มานานน
Reference
- 9 Docker Extensions Every Developer Must Try - DEV Community
- Azure File Storage as a Docker Plugin (jmaitrehenry.ca)
Discover more from naiwaen@DebuggingSoft
Subscribe to get the latest posts sent to your email.



