เลิกพูดว่า It works on my machine! สรุปครบจบทุก Concept Docker ในโพสต์เดียว
Docker Fundamental: สรุปครบเครื่องเรื่อง Container
เลิกพูดว่า It works on my machine! สรุปครบจบทุก Concept Docker ในโพสต์เดียว

Docker Fundamental: สรุปครบเครื่องเรื่อง Container
“จบปัญหา Dependency ตีกันด้วย Blueprint เพียงใบเดียว”
ทุกคนคงเคยได้ยิน It Work from My Machine!?!! ปัญหาก็เกิดจาก Version ต่าง ๆ ของ Dependency มันไม่ตรงกันในแต่ละเครื่อง เครื่องเรา node v2.0 แต่เครื่อง server v1.0 พอเราเอาโค้ดที่รันผ่านในเครื่องเราไปรันในเครื่อง server มันก็รันไม่ได้ แต่ปัญหานี้จะจบลงเมื่อเราเอา Docker มาใช้ในงานของเรา ทำให้ไม่ว่าเราจะเอาโค้ด ไปรันที่ไหน ก็รันได้ทุกเครื่อง วันนี้ผมจะพาทุกคนมารู้จักกับ Docker กันครับ โดยเราเริ่มจาก Container ที่เป็นหัวใจหลักของ Docker กันครับ

Container vs VM: ต่างกันยังไง?
Container
- Container จะรวม App Layer พวก Package Code และ Dependency เข้าด้วยกัน
- ถ้ามีหลาย Container มันจะรันในเครื่องเดียวกับเราและแชร์ OS กับ container อื่น ๆ
- ในการรัน Container แต่ละตัวจะ process แยกกัน ทำให้ใช้เวลา process เร็วกว่า VM
- ขนาดของ Container นั้นเล็กกว่า VM ทำให้สามารถรัน VM หรือ OS แยกขึ้นมาได้
VM (Virtual Machine)
- VM จะจำลองเครื่อง Server
- VM จะจัดการใน Layer Physical Hardware ซึ่งเราสามารถเปลี่ยนจาก 1 เครื่อง Server เป็น หลาย Server ได้ในเครื่องเดียว ผ่าน VMs
- VM ใช้ Hypervisor (ตัวจัดการ Virtual Machine) ในการทำให้ 1 Server มีได้หลาย VMs
- VM จะ Copy พวก OS, Binary File ต่าง ๆ มาหมด ทำให้มีขนาดมากกว่า 10GBs
- ทำให้ VM นั้นจะ Boot ช้ากว่า Container
3 เสาหลักของ Docker
โดยมาเริ่มจาก Main Concept การทำงานของ Docker กันก่อน

Dockerfile คือ script ที่กำหนดขั้นตอนทั้งก่อนและหลังสร้าง Image ทำก่อนจะ Build เป็น Image

โดยการเขียน Dockerfile เราจะเอาขั้นตอนที่มีการเปลี่ยนแปลงบ่อยไว้ในส่งล่าง ๆ ของไฟล์ และขั้นตอนที่มีการเปลี่ยนแปลงน้อยจะไว้ในส่วนบน ๆ ของไฟล์
Docker จะเก็บผลลัพธ์ของแต่ละบรรทัดใน Dockerfile เป็น Layer ถ้าบรรทัดบน ๆ ไม่เปลี่ยน Docker จะหยิบของเก่าจาก Cache มาใช้ทันที ทำให้ Build ครั้งต่อไปเร็วปรู๊ดปร๊าด!
ในโปรเจกต์เราควรมีไฟล์ชื่อ .dockerignore (ฟีลเดียวกับ .gitignore เลย) เพื่อบอก Docker ว่า “ไม่ต้องเอาไฟล์พวกนี้เข้าไปใน Image นะ” เช่น node_modules หรือพวกไฟล์ Log ต่าง ๆ วิธีนี้จะช่วยให้ Image ของเรา ตัวเบาและ Build เร็วขึ้นมหาศาล ครับ
Image คือ เหมือน BluePrint ของ Container ที่รวมโค้ดและ Env โดยจะอ่านอย่างเดียว และทำให้เป็น Binary พร้อมที่จะ Run เป็น Container ฟีลเหมือนไฟล์ .exe โดยเราสามารถเอา Image ไปรันที่ไหนก็ได้
//docker build -t <ชื่อ Image>:<Version(optional)> <WorkDirectory ของ Dockerfile>
docker build -t my-app:1.0 .
Container คือ เป็นสิ่งที่ได้จากการรัน Image เหมือนเรารันไฟล์ .exe แล้วโปรแกรมมันรันขึ้นมา
docker run my-app:1.0
เจาะลึก Architecture (ตาม Diagram)
อันนี้คือ Basic คร่าว ๆ ของ Docker ทีนี้เรามาเจาะลึกกันดีกว่า ไล่ไปตาม ภาพ Diagram นี้

โดยเรามาเริ่มที่
Docker Client ก็คือ Command line(CLI) ต่าง ๆ ของ Docker ที่เราใช้กัน เช่น พวก docker build, docker run โดยเมื่อเรารันคำสั่งแล้วเนี่ย มันจะส่งคำสั่งเราไปให้
Docker Daemon ตัวนี้เป็น Engine หลักของ Docker ที่จะคอยทำหน้าที่ต่าง ๆ ตาม CLI และจะเป็นเหมือนตัวควบคุมการทำงานของ Docker
Docker Image จริง ๆ จะมี Practice ที่เขาทำ ๆ กันอยู่ก็คือ เมื่อเราได้ Image แล้วเนี่ย เราสามารถ Push Image ของเราไปเก็บไว้ที่ Docker Registry แล้วสามารถให้คนอื่น Pull Image เราไปใช้ต่อได้เลย “เหมือนเราทำเกมหรือโปรแกรมไว้แล้วเราทำเป็นไฟล์ .exe แล้วอัพขึ้นเน็ต แล้วให้คนอื่นมาโหลด .exe ไปใช้/ไปเล่น”
Docker Registry เป็นเหมือน Github ของชาว Dev โดยที่ Docker Registry มันจะเก็บ Image แทน Source code ซึ่งที่นิยมกันก็จะเป็น “DockerHub”
Image เราสามารถ Pull Image บน Docker Registry มาใช้ได้ โดยเรียกเขียนใน Dockerfile เพื่อเรียกใช้ Image ที่เราต้องการ เช่น FROM node:20
Scaling up with Docker Compose
ที่อธิบายไปด้านบนมันเป็นการทำงานแบบ Image เดียว Container เดียว แต่ทีนี้ถ้าเราอยาก Build หลาย Image รันหลาย Container ตามจำนวนครั้งที่เราอยากได้หรอ?? ป่าวเลยครับ มันมี 1 ตัวที่จะมาช่วยเราจัดการ Image และ Container หลาย ๆ ตัว ได้ในคราวเดียว นั้นก็คือออ Docker Compose ครับ
Docker Compose เป็นตัวที่จะรวมหลาย ๆ Image มาเข้าด้วยกัน และจัดการในทีเดียว โดยจะมีไฟล์ docker-compose.yaml ซึ่งในนั้นจะเรียก Image ว่า Service
services:
web:
build: .
ports:
- "${APP_PORT}:5000"
environment:
- REDIS_HOST=${REDIS_HOST}
- REDIS_PORT=${REDIS_PORT}
depends_on:
redis:
condition: service_healthy
redis:
image: redis:alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
start_period: 10s
โดยในตัวอย่างจะมี Service web กับ redis พอรันคำสั่ง
docker compose up //มันจะรัน docker-compose.yaml ถ้ามี Image อยู่แล้ว
docker compose up --build //มันจะ Build Image ก่อนแล้วค่อยรัน Imaga
docker compose down //หยุดรัน container
โดย 2 Service นี้จะคุยกันผ่าน Network โดย Docker จะมี DNS เป็นของตัวเองทำให้แค่ service web เรียก servive redis ผ่านชื่อได้เลยเช่น redis:6379 ตัว Docker มันจะรู้เองว่าจะต้องวิ่งไป IP Address ของตัว Container ตัวไหน
เวลา Container คุยกันเองภายใน Network ของ Docker ให้ใช้ Port จริงของ Service นั้น ๆ ได้เลย (เช่น
redis:6379) ไม่ต้องใช้ Port ที่เรา Map ออกมาข้างนอก (เช่น8080) เพราะนั่นเอาไว้ให้เครื่อง Host เราเข้าหา Container เท่านั้น
Data & Development (Volume & Bind Mount)
Source Code ของเรามัน Update ตลอดเวลา ถ้าเกิด Build เป็น Image แล้ว มันจะ Snapshot แค่ Code Version ตอนนั้น ซึ่งเราจะต้อง “compose down” กับ “compose up” ใหม่ทุกครั้งที่ Code เรามีการเปลี่ยนแปลง ที่นี้เราไม่ทำอย่างงั้น Docker สามารถ Bind Mount ได้ ก็คือเหมือนเปิดช่องทางไว้ให้ ถ้า Code จากภายนอกมีการเปลี่ยนแปลง ก็จะ Map เอา Code เข้ามาใน Container ซึ่งนั้นก็คือเหมือนทำ Hot Reload แต่ทั้งนี้อันนี้เหมาะแค่กับตอน Development ส่วนใน Production จะไม่ทำกันเพราะต้องการความนิ่งของ App
ถ้าเรามี Container Postgres แล้วเราเผลอ “compose down -v” ข้อมูลใน Postgres มันก็จะหายไป แต่ไม่ต้องห่วงครับ Docker สามารถ Map Volume ได้ ก็คือเอา Data ที่อยู่ใน Container ของ Database เราไปเก็บไว้ที่ข้างนอก Container ซึ่งจะไม่ถูกกระทบ ถ้าไม่ได้ลบไฟล์นั้นในเครื่องเรา
- ก็คือก่อน Map Volume Docker จะเป็น Stateless ข้อมูลไม่ผูกติดกับอะไรเลย
- หลังจาก Map Volume Docker จะเป็น Stateful ข้อมูลยังคงอยู่ (Persist) แม้ Container จะถูกลบหรือหยุดทำงาน
แล้วเราจะเข้าถึง Container ได้ยังไง โดยเราจะเข้าถึงโดยการเปิดประตูให้มันครับ โดยการ Map Port จากใน Container กับ นอก Container เช่น 8080:80
เลขหน้าคือเครื่องเรา (Host) : เลขหลังคือ ในตู้ (Container) ก็คือเข้าผ่าน 8080 วิ่งไปหา 80 ในตู้)
เล่น Docker ไปนาน ๆ แล้วเครื่องเต็ม?
ถ้าเริ่มรู้สึกว่าเนื้อที่ในคอมหายไปแปลก ๆ ลองใช้คำสั่งกวาดบ้านดูครับ
docker system prune
คำสั่งเดียวจะช่วยกวาดพวก Container ที่หยุดรัน หรือ Image ที่ไม่ได้ใช้แล้วทิ้งไป เครื่องจะกลับมาโล่งปรู๊ดปร๊าดเหมือนเดิม!
메타데이터
- post_id
- 894ce0bd7bf4
- slug
- เลิกพูดว่า-it-works-on-my-machine-สรุปครบจบทุก-concept-docker-ในโพสต์เดียว-894ce0bd7bf4
- url
- https://medium.com/@pakkapon-chomchoey/%E0%B9%80%E0%B8%A5%E0%B8%B4%E0%B8%81%E0%B8%9E%E0%B8%B9%E0%B8%94%E0%B8%A7%E0%B9%88%E0%B8%B2-it-works-on-my-machine-%E0%B8%AA%E0%B8%A3%E0%B8%B8%E0%B8%9B%E0%B8%84%E0%B8%A3%E0%B8%9A%E0%B8%88%E0%B8%9A%E0%B8%97%E0%B8%B8%E0%B8%81-concept-docker-%E0%B9%83%E0%B8%99%E0%B9%82%E0%B8%9E%E0%B8%AA%E0%B8%95%E0%B9%8C%E0%B9%80%E0%B8%94%E0%B8%B5%E0%B8%A2%E0%B8%A7-894ce0bd7bf4
- canonical_url
- https://medium.com/@pakkapon-chomchoey/%E0%B9%80%E0%B8%A5%E0%B8%B4%E0%B8%81%E0%B8%9E%E0%B8%B9%E0%B8%94%E0%B8%A7%E0%B9%88%E0%B8%B2-it-works-on-my-machine-%E0%B8%AA%E0%B8%A3%E0%B8%B8%E0%B8%9B%E0%B8%84%E0%B8%A3%E0%B8%9A%E0%B8%88%E0%B8%9A%E0%B8%97%E0%B8%B8%E0%B8%81-concept-docker-%E0%B9%83%E0%B8%99%E0%B9%82%E0%B8%9E%E0%B8%AA%E0%B8%95%E0%B9%8C%E0%B9%80%E0%B8%94%E0%B8%B5%E0%B8%A2%E0%B8%A7-894ce0bd7bf4
- author_url
- https://medium.com/@pakkapon-chomchoey
- status
- ok
- fetched_at
- 2026-06-09 15:37:30