Build Image
เรียนรู้วิธีแปลง Dockerfile ให้กลายเป็น image ด้วยคำสั่ง docker build ทำความเข้าใจ build context, tag, และกระบวนการ layer-by-layer พร้อมดู output จริง แก้ปัญหาที่พบบ่อย และฝึกดู image ที่สร้างเสร็จด้วย docker images
ภาพจำสำคัญบทนี้
docker build -t ชื่อ:tag . | build context = ไฟล์ทั้งหมดใน . ที่ Docker มองเห็น | CACHED = ใช้ layer เก่าที่ไม่เปลี่ยน | docker images เพื่อยืนยัน build สำเร็จ
ส่วนที่ 1
Build image คืออะไร
ลองนึกภาพว่าคุณอบเค้กจากสูตร — สูตรอาหารคือ Dockerfile, เตาอบที่ทำตามสูตรคือ docker build, และเค้กที่ออกมาพร้อมรับประทานคือ image "Build image" (บิลด์อิมเมจ) คือกระบวนการที่ Docker อ่าน Dockerfile แล้วประกอบทุกอย่าง — OS, runtime, dependencies, source code — เข้าด้วยกันเป็นไฟล์ที่พร้อมใช้งานเรียกว่า image (อิมเมจ) image คือ snapshot (สแนปช็อต) ที่แช่แข็งไว้ ณ เวลาที่ build — ไม่เปลี่ยนแปลงเองอีกต่อไป สามารถนำไปรันเป็น container ได้ทันทีในทุกเครื่องที่มี Docker
- image คือ snapshot สมบูรณ์ของทุกสิ่งที่แอปต้องการ — OS, runtime, dependencies, และ source code
- build ครั้งเดียว ใช้ได้ทุกที่ที่มี Docker ไม่ว่าจะเป็น laptop, server, หรือ cloud
- docker build คือคำสั่งที่แปลง Dockerfile (สูตร) ให้กลายเป็น image (เค้กสำเร็จรูป)
ส่วนที่ 2
ทำไมต้อง build image
ก่อนมี Docker ถ้าต้องการ deploy แอปไปเครื่องใหม่ต้องติดตั้ง Node.js, npm packages, ตั้งค่า environment ทุกอย่างด้วยมือ ซึ่งใช้เวลาและเกิดข้อผิดพลาดได้ง่าย image แก้ปัญหาทั้งหมดนี้ เพราะมันบรรจุทุกอย่างไว้ในที่เดียวแล้ว
ประเด็นที่ 1
ความสม่ำเสมอ (Consistency) — image เดียวกันรันได้ผลเหมือนกันทุกเครื่อง ไม่มี 'ทำงานในเครื่องฉันแต่ไม่ทำงานในเครื่องเธอ'
ประเด็นที่ 2
ความเร็วใน deploy — ไม่ต้องติดตั้งซ้ำทุกครั้ง แค่ pull image แล้ว run ได้เลย
ประเด็นที่ 3
ทำงานร่วมกับ CI/CD — build ครั้งเดียว push ไป registry แจกจ่ายได้ทุกที่โดยอัตโนมัติ
ประเด็นที่ 4
ย้อนกลับเวอร์ชันได้ง่าย — แต่ละ image tag คือ snapshot ที่สามารถ rollback กลับไปได้ทุกเมื่อ
ส่วนที่ 3
ความสัมพันธ์ระหว่าง Dockerfile กับการ build
Dockerfile เป็น input หลักของกระบวนการ build — Docker daemon อ่านทีละ instruction แล้วประกอบเป็น layer สุดท้ายได้ image สมบูรณ์ ทั้งสามสิ่งนี้ทำงานร่วมกันเป็นลำดับ: Dockerfile → docker build → Image
| บทบาท | ทำหน้าที่อะไร | ตัวอย่าง |
|---|---|---|
| Dockerfile | บอก Docker ว่าจะสร้าง image อย่างไร — สูตรที่เราเขียน | FROM node:20-alpine, RUN npm ci |
| docker build | อ่าน Dockerfile แล้วประกอบทีละชั้น (layer) จนได้ image | docker build -t my-app:1.0 . |
| Image | ผลลัพธ์สุดท้ายที่พร้อมนำไป run เป็น container ได้ทันที | my-app:1.0, node:20-alpine |
ส่วนที่ 4
docker build ทำงานอย่างไรโดยภาพรวม
เมื่อเราสั่ง docker build Docker จะทำงานเป็นลำดับขั้นตอนดังนี้:
ภาพที่ 1 — flow: Dockerfile + build context → docker build → image
ภาพที่ 1: Dockerfile (สูตร) + build context (ไฟล์ทั้งหมด) → docker build ประกอบทีละ instruction → Image พร้อมใช้งาน → นำไป docker run เป็น container
ส่วนที่ 5
ความหมายของ build context
build context คือชุดไฟล์ที่ Docker "มองเห็น" และ "เข้าถึงได้" ระหว่างขั้นตอน build เมื่อสั่ง docker build . — จุด (.) ท้ายคำสั่งคือ path ของ build context ซึ่งหมายถึงโฟลเดอร์ปัจจุบัน Docker จะส่งไฟล์ทุกตัวในโฟลเดอร์นั้นไปให้ daemon ก่อนเริ่ม build — ดังนั้นถ้ามีไฟล์ใหญ่ที่ไม่จำเป็น การส่ง context จะช้าลงมาก
- build context คือโฟลเดอร์ที่ระบุด้วย . หรือ path ต่อท้ายคำสั่ง docker build — ไฟล์นอก context จะถูกเข้าถึงไม่ได้
- คำสั่ง COPY ใน Dockerfile เข้าถึงได้เฉพาะไฟล์ที่อยู่ใน build context เท่านั้น
- ใช้ .dockerignore เพื่อกัน node_modules, .git และไฟล์ที่ไม่จำเป็นออกจาก context (บทถัดไป)
- context ใหญ่ = build ช้า — สังเกตข้อความ 'Sending build context to Docker daemon' พร้อมขนาดได้ใน output
ส่วนที่ 6
คำสั่งพื้นฐาน: docker build
คำสั่ง docker build มีรูปแบบพื้นฐานคือ docker build [options] path — โดย path คือ build context ที่ต้องระบุเสมอ
flag -t ใช้ตั้งชื่อ (tag) image — ควรใส่ทุกครั้งเพื่อให้หา image ได้ง่าย จุด (.) ท้ายคำสั่งคือ build context
ส่วนที่ 7
tag คืออะไร
tag (แท็ก) คือ label หรือป้ายชื่อที่ติดกับ image เพื่อให้จำและเรียกใช้งานได้ง่าย รูปแบบคือ name:tag เช่น my-app:1.0 — ถ้าไม่ระบุ tag Docker จะใช้ :latest อัตโนมัติ ซึ่งอาจทำให้สับสนเมื่อมีหลายเวอร์ชัน เพราะ latest ของคนนี้กับคนนั้นอาจไม่เหมือนกัน
| ส่วน | ความหมาย | ตัวอย่าง |
|---|---|---|
| ชื่อ image (name) | ชื่อโปรเจกต์หรือแอป — ตั้งให้สื่อความหมาย | my-app, nginx, node |
| tag | เวอร์ชัน หรือ variant ของ image — ระบุสิ่งที่แตกต่าง | 1.0, latest, prod, alpine |
| ชื่อเต็ม (full reference) | name:tag ใช้อ้างอิง image ในทุกคำสั่ง | my-app:1.0, nginx:1.25-alpine |
ส่วนที่ 8
ตัวอย่างการตั้งชื่อ image และ tag
รูปแบบการตั้งชื่อที่ดีช่วยให้ทีมเข้าใจได้ทันทีว่า image แต่ละตัวคืออะไรและอยู่ในสถานะไหน
ตั้งชื่อให้สื่อความหมาย เช่น ชื่อแอป:เวอร์ชัน หรือ ชื่อแอป:สภาพแวดล้อม — หลีกเลี่ยง :latest ใน production
ภาพที่ 2 — Docker อ่าน instruction ทีละชั้นระหว่าง build
ภาพที่ 2: Docker อ่าน Dockerfile จากบนลงล่าง (Instruction 1→5) แต่ layer จะซ้อนกันจากล่างขึ้นบน — layer ล่างสุดคือ base image, layer บนสุดคือการเปลี่ยนแปลงล่าสุด
ส่วนที่ 9
Docker อ่าน Dockerfile ทีละบรรทัดอย่างไร
ทุกครั้งที่ docker build ทำงาน Docker จะอ่าน Dockerfile จากบนลงล่างทีละ instruction — แต่ละ instruction สร้าง layer (เลเยอร์) ใหม่ที่ซ้อนบน layer ก่อนหน้า สิ่งสำคัญที่ต้องเข้าใจคือ layer cache — ถ้า instruction และ input ของมัน (ไฟล์, คำสั่ง) ไม่ได้เปลี่ยนแปลงจาก build ครั้งก่อน Docker จะใช้ผลลัพธ์เก่าแทนการรันใหม่ ทำให้ build เร็วขึ้นมาก
แต่ละ instruction สร้าง layer — เรียงจาก layer ที่เปลี่ยนน้อยไปหามาก เพื่อใช้ประโยชน์จาก cache ได้สูงสุด
ส่วนที่ 10
ตัวอย่าง output จากการ build และอธิบายว่ากำลังเกิดอะไรขึ้น
output ของ docker build บอกสถานะของแต่ละขั้นตอนได้อย่างละเอียด — อ่านให้เป็นแล้วจะรู้ทันทีว่า build ช้าตรงไหนและทำไม
CACHED หมายความว่า Docker ใช้ผลลัพธ์เก่า ไม่ต้องรันใหม่ — ยิ่งมี CACHED มาก build ยิ่งเร็ว
| บรรทัดใน output | ความหมาย |
|---|---|
| [+] Building 12.3s (9/9) FINISHED | build ทั้งหมดใช้เวลา 12.3 วินาที มี 9 step เสร็จครบ |
| CACHED [2/5] WORKDIR /app | Docker ใช้ cache ของ layer นี้ ไม่ต้องรันซ้ำ — ประหยัดเวลา |
| [5/5] COPY . . | layer นี้ไม่มี cache (source code เปลี่ยน) ต้องรันใหม่ |
| naming to docker.io/library/my-app:1.0 | image ถูก tag เสร็จแล้ว พร้อมใช้งาน |
ภาพที่ 3 — image ที่ build แล้วนำไป run เป็น container ได้ทันที
ภาพที่ 3: image ที่ build เสร็จแล้วสามารถนำไป docker run สร้าง container ได้หลายตัวพร้อมกัน — รันบน port ต่างกัน, เครื่องต่างกัน, หรือใน CI/CD ก็ได้
ส่วนที่ 11
วิธีดู image ที่ build เสร็จแล้ว
หลัง build สำเร็จ image จะถูกเก็บไว้ใน local image store ของ Docker สามารถดูรายการได้ด้วยคำสั่ง docker images หรือ docker image ls
สองคำสั่งนี้ให้ผลเหมือนกัน — docker image ls เป็นรูปแบบ subcommand ใหม่ที่แนะนำ
คอลัมน์สำคัญคือ REPOSITORY (ชื่อ), TAG (เวอร์ชัน), IMAGE ID (รหัส), และ SIZE (ขนาด)
ส่วนที่ 12
ข้อผิดพลาดที่พบบ่อยและวิธีแก้
รายการด้านล่างนี้คือปัญหาที่ผู้เริ่มต้นมักเจอเมื่อสั่ง docker build พร้อมสาเหตุและวิธีแก้ไข
| ข้อผิดพลาด | สาเหตุ | วิธีแก้ |
|---|---|---|
| unable to find Dockerfile หรือ no such file or directory | รัน docker build จาก directory ที่ไม่มี Dockerfile หรือสะกดชื่อไฟล์ผิด | cd ไปที่โฟลเดอร์ที่มี Dockerfile ก่อน หรือใช้ -f ระบุ path: docker build -f path/to/Dockerfile . |
| Sending build context ช้ามาก หรือขนาด context ใหญ่ผิดปกติ | มีไฟล์ใหญ่ใน build context เช่น node_modules (100MB+) หรือ .git ที่ไม่จำเป็น | สร้างไฟล์ .dockerignore แล้วระบุ node_modules และ .git เพื่อกันออกจาก context |
| COPY failed: file not found in build context | ไฟล์ที่ระบุใน COPY ไม่อยู่ใน build context หรือ path ผิด | ตรวจสอบว่าไฟล์อยู่ใน directory ที่รัน docker build และ path ใน COPY ถูกต้อง |
| หา image ไม่เจอหลัง build สำเร็จ | ลืมใส่ -t ทำให้ image มีแค่ ID hex ยาว จำและอ้างอิงได้ยาก | ใช้ docker build -t ชื่อ:tag . เสมอ หรือ tag ทีหลังด้วย docker tag ID ชื่อ:tag |
ส่วนที่ 13
สถานการณ์จริงในการ build แอป
ดู workflow จริงตั้งแต่เขียนโค้ดจนถึง run container — ทำตามลำดับนี้ทุกครั้งที่แก้ code แล้วอยากทดสอบใน container
จำขั้นตอนนี้ไว้: แก้โค้ด → build → ตรวจสอบ → run
- แก้ Dockerfile หรือ source code แล้วต้อง build ใหม่เสมอ — image เก่าไม่อัปเดตเอง
- ใช้ tag ที่มีความหมาย เช่น :dev, :1.0, :prod เพื่อไม่สับสนกัน
- ตรวจสอบ image ด้วย docker images ก่อน run เพื่อยืนยันว่า build สำเร็จและ tag ถูกต้อง
ส่วนที่ 14
สรุปท้ายบทแบบจำง่าย
จำ 4 จุดนี้แล้วใช้ docker build ได้ทันที: 1. docker build -t ชื่อ:tag . — คำสั่งหลักที่ใช้ทุกวัน จำ -t และ . ให้ขึ้นใจ 2. build context = โฟลเดอร์ที่ . ชี้ไป — Docker ส่งทุกไฟล์ในนั้นให้ daemon ก่อน build 3. CACHED ใน output = Docker ประหยัดเวลาด้วย layer cache — ดีกว่า = ยิ่งช้า 4. docker images ใช้ยืนยันว่า build สำเร็จและ image พร้อมใช้
- docker build -t ชื่อ:tag . — สร้าง image พร้อม label ที่จำได้
- build context คือไฟล์ทั้งหมดที่ Docker มองเห็น — กรองด้วย .dockerignore เพื่อให้เร็ว
- tag = ชื่อ:เวอร์ชัน — ช่วยให้จำ, ย้อนกลับ, และจัดการ image ได้ง่าย
- docker images / docker image ls — ดูรายการ image ทั้งหมดในเครื่อง
- CACHED = Docker ใช้ผลลัพธ์เก่า ไม่ต้องรัน instruction นั้นซ้ำ
- แก้โค้ดแล้วต้อง docker build ใหม่ก่อน — image เก่าไม่เปลี่ยนแปลงเอง
แบบฝึกหัด
ทดสอบความเข้าใจ
ลองตอบคำถามต่อไปนี้ด้วยตัวเอง แล้วกดดูแนวเฉลยเพื่อเปรียบเทียบ