ข้ามไปยังเนื้อหา

บทนำและแนวคิด — ภาพรวมโมดูล

นักพัฒนาทุกคนเคยได้ยินประโยคนี้: “บนเครื่องผมมันรันได้นะ” แอปทำงานได้สมบูรณ์ตอนพัฒนา แต่พังบน staging หรือ production เพราะ OS ต่างกัน library คนละเวอร์ชัน หรือขาด environment variable Docker ลดช่องว่างนั้นด้วยการแพ็กแอปพร้อมทุกอย่างที่ต้องใช้ — runtime, dependency และ configuration — ให้เป็นหน่วยเดียวที่พกพาได้ เรียกว่า container

สิ่งที่ได้จาก Docker:

  • สภาพแวดล้อมสม่ำเสมอ — image เดียวกันให้ userland เดียวกันทั้งบน laptop, CI server และ cloud VM (kernel ข้างใต้ยังเป็นของ host ดู Containers vs VMs)
  • การแยกตัว (Isolation) — แต่ละ container มีมุมมอง filesystem และ process ของตัวเอง แอปจึงไม่รบกวนกัน
  • ความเร็ว — ไม่ต้อง boot guest OS วัดจริงด้านล่าง: docker run แบบ warm เสร็จในราว 1 ใน 4 วินาที
  • Reproducibility — Dockerfile คือสูตรที่แม่นยำ build จาก base image ที่ pin เวอร์ชันและ input เดียวกันจะได้ผลเดียวกัน
บทเรียนสิ่งที่คุณจะได้เรียนรู้
หน้านี้ปัญหาที่ Docker แก้ container แรก ตัวเลขเวลาจริง
What is Docker?สถาปัตยกรรม: client, daemon, image, registry — พิสูจน์ผ่าน socket จริง
Containers vs VMsการแชร์ kernel, namespace, cgroup — พิสูจน์ด้วย uname, /proc และ memory.max
Install & Verifyติดตั้ง Docker ตรวจสอบการติดตั้ง และกลุ่ม docker
Your First Containercontainer แบบ interactive + detached, docker ps, docker stop และ timeout 10 วินาที

ทุกคำสั่งและทุก output ในคอร์สนี้รันบนเครื่องเดียวกัน เมื่อ 2026-09-30:

Componentเวอร์ชัน (จาก docker version / docker compose version)
Docker Desktop4.81.0 (macOS, Apple Silicon, linux/arm64)
Docker Engine29.6.1 (API 1.55, ขั้นต่ำ 1.40)
containerd / runcv2.2.5 / 1.3.6
Buildx / BuildKitv0.35.0-desktop.2 / v0.31.1
docker compose pluginv5.3.0 (ไม่มี binary docker-compose แยก และไม่มี “Compose v2” อีกแล้ว)

output ที่วางไว้คือผลจริงจากเครื่อง Mac นี้ ส่วนที่ Linux Engine ทำงานต่างออกไปจะมี callout บอก ขนาด image เป็นขนาดของ arm64 ส่วน amd64 จะต่างเล็กน้อย

วิธีที่เร็วที่สุดในการยืนยันว่า Docker ทำงานได้คือ image ทางการ hello-world Docker จะดึง image จาก Docker Hub หากยังไม่มีในเครื่อง สร้าง container พิมพ์ข้อความ แล้วจบการทำงาน

Terminal window
docker run hello-world

ลองรันตอนนี้ด้วย playground ด้านล่าง:

docker run hello-world

จับเวลารัน container ที่ไม่ทำอะไรเลย (true จบทันที) 3 ครั้ง โดยมี image อยู่แล้ว บน Mac เครื่องนี้ (wall clock รวมเวลา start CLI และการเดินทางเข้า VM):

$ docker run --rm alpine:3.24 true # 0.25 s
$ docker run --rm alpine:3.24 true # 0.24 s
$ docker run --rm alpine:3.24 true # 0.25 s

และ cold start จริง ๆ — image ไม่อยู่ในดิสก์ จึงรวมเวลา pull จาก Docker Hub (สั่ง docker rmi hello-world ก่อน):

$ docker run --rm hello-world # 4.21 s (ส่วนใหญ่คือ pull ผ่านเครือข่าย)
$ docker run --rm hello-world # 0.25 s (warm)

ดังนั้นคำว่า “มิลลิวินาที” ในโฆษณาหมายความว่า การสร้าง namespace กับ cgroup แล้ว exec process นั้นถูกมาก และไม่มี kernel ให้ boot สิ่งที่คุณรอจริง ๆ คือการ pull (ครั้งแรก) และเวลา start ของแอปคุณเอง VM ต้อง boot guest kernel และ init system ทั้งชุดก่อนที่ process ของคุณจะเริ่ม ความต่างตรงนั้นคือประเด็น ไม่ใช่ตัวเลขที่แน่นอน

flowchart LR
  subgraph MAC["macOS (เครื่อง Mac ของคุณ)"]
    cli["docker CLI (darwin/arm64)"]
    sock["~/.docker/run/docker.sock"]
  end
  subgraph VM["Docker Desktop Linux VM (kernel linuxkit)"]
    engine["dockerd + containerd + runc"]
    c1["container ของคุณ (linux/arm64)"]
  end
  cli --> sock --> engine --> c1
อะไรรันที่ไหนบน Docker Desktop สำหรับ Mac

AI assistant มักเขียนสคริปต์ตรวจ “Docker พร้อมหรือยัง” ที่ดูสมเหตุสมผล สคริปต์นี้เจอได้บ่อยตอนต้นของสคริปต์ CI และ setup:

🐛 หา bug ในโค้ดนี้

#!/bin/sh
# AI: "verify that Docker is installed and running before the build"
if docker --version; then
echo "Docker is ready"
docker build -t myapp:ci .
fi
เฉลย

docker --version ถาม binary ของ client เท่านั้นว่าเวอร์ชันอะไร จึงสำเร็จแม้ไม่มี daemon ให้เชื่อมต่อ พิสูจน์โดยชี้ CLI ไปที่ socket ที่ไม่มีอยู่:

$ DOCKER_HOST=unix:///nonexistent.sock docker --version
Docker version 29.6.1, build 8900f1d
$ echo $?
0
$ DOCKER_HOST=unix:///nonexistent.sock docker version --format '{{.Server.Version}}'
failed to connect to the docker API at unix:///nonexistent.sock; check if the path is correct and if the daemon is running: dial unix /nonexistent.sock: connect: no such file or directory
$ echo $?
1

สคริปต์จะพิมพ์ “Docker is ready” แล้วค่อยล้มที่ docker build พร้อม log ที่ชวนสับสน ให้ถาม server แทน — ทั้ง docker info และ docker version --format จะ exit ด้วยค่าไม่ใช่ศูนย์เมื่อเข้าถึง daemon ไม่ได้:

scripts/check-docker.sh
#!/bin/sh
set -eu
if ! docker info >/dev/null 2>&1; then
echo "Docker daemon is not reachable (is Docker Desktop running?)" >&2
exit 1
fi
echo "Docker is ready: $(docker version --format '{{.Server.Version}}')"

มอง Docker เป็นสามชั้นซ้อนกัน: client ที่แปลคำสั่งเป็น API call, engine ที่เป็นเจ้าของ image, container, network และ volume, และ Linux kernel ที่แยก process จริง ๆ container ไม่ใช่คอมพิวเตอร์เครื่องเล็ก แต่เป็น process ธรรมดาของ Linux ที่ kernel ถูกสั่งให้แสดงมุมมอง filesystem, network และ process table แบบส่วนตัวให้ มันจึง start ในราว 1 ใน 4 วินาที และเร็วกว่า process ที่อยู่ข้างในไม่ได้

ทางเลือกข้อดีข้อเสีย
ใช้ container แทนการติดตั้งบน hostimage เดียวกันทุกที่ สร้าง/ทิ้ง environment สะอาด ๆ ได้ต้องดูแล engine, image และ registry
Docker Desktop บน Mac/Windowsตัวติดตั้งเดียวได้ CLI, engine, Compose, Buildxengine อยู่ใน VM: ใช้ RAM เพิ่ม, file sharing มี overhead, IP ของ bridge เข้าจาก host ไม่ได้
Pull จาก Docker Hub ตอนรันครั้งแรกไม่ต้องตั้งค่าcold start เสียเวลาหลายวินาทีและนับรวมใน pull rate limit
  • “container start ในมิลลิวินาที” การตั้งค่า isolation ถูกจริง แต่วัดปลายทาง-ปลายทางได้ 0.25 วินาทีเมื่อ warm และ 4.21 วินาทีเมื่อ cold เวลา start ของแอปคุณเองมักเป็นตัวหลัก
  • “Docker รับประกันพฤติกรรมเหมือนกันทุกที่” image เหมือนกัน แต่ kernel, สถาปัตยกรรม CPU (arm64 ที่นี่) และการตั้งค่าของ host ไม่เหมือน image ที่มีแต่ amd64 จะรันผ่าน emulation บน Apple Silicon
  • “docker --version พิสูจน์ว่า Docker ใช้งานได้” มันพิสูจน์แค่ว่าติดตั้ง client แล้ว ให้ใช้ docker info
Docker แก้ปัญหาหลักอะไร?
Docker container คืออะไร?
ฟีเจอร์ใดของ Linux kernel ที่ทำให้ container แยกตัวได้?
บน Mac docker version แสดง OS/Arch: darwin/arm64 ฝั่ง client และ linux/arm64 ฝั่ง server ข้อมูลนี้บอกอะไร?
สคริปต์ CI รัน if docker --version; then ... docker build ...; fi เพื่อเช็คว่า Docker พร้อม มีอะไรผิด?