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

Build, Tag และ Build Context

docker build อ่าน Dockerfile แล้วสร้าง image ออกมา syntax พื้นฐานคือ:

Terminal window
docker build [OPTIONS] PATH

อาร์กิวเมนต์ PATH (โดยทั่วไปคือ .) เรียกว่า build context คือไดเรกทอรีที่ Docker ส่งไปให้ build daemon ไฟล์ที่อยู่ใน build context จะใช้ได้กับ instruction COPY ภายใน Dockerfile ส่วนไฟล์ที่อยู่นอก build context จะเข้าถึงไม่ได้

Terminal window
docker build .

คำสั่งนี้ส่งไดเรกทอรีปัจจุบันเป็น build context หากไม่มี -t image ที่ได้จะไม่มีชื่อ — มีแค่ hex digest เท่านั้น คุณจึงแทบจะเพิ่ม -t เสมอ

แฟล็ก -t กำหนด name:tag ที่อ่านเข้าใจได้ให้กับ image:

Terminal window
docker build -t myapp:1.0 .

รูปแบบเต็มของ tag คือ:

[registry/][owner/]name:tag

ตัวอย่าง:

myapp:1.0
myapp:latest
ghcr.io/acme/myapp:1.0
docker.io/library/node:22-alpine

หากคุณละส่วน tag ไว้ Docker จะใช้ค่าเริ่มต้นเป็น :latest

Terminal window
docker images

ผลลัพธ์ที่คาดหวัง:

REPOSITORY TAG IMAGE ID CREATED SIZE
myapp 1.0 a3f2b1c9d4e7 2 minutes ago 145MB
myapp latest a3f2b1c9d4e7 2 minutes ago 145MB
node 22-alpine 1b2c3d4e5f60 3 weeks ago 52MB

docker tag เพิ่มชื่อหรือ tag ใหม่ให้กับ image ที่มีอยู่แล้วโดยไม่คัดลอกตัว image ทั้งสองชื่อจะชี้ไปยัง image ID เดียวกัน

Terminal window
# Promote a build image to a release name
docker tag myapp:1.0 myapp:stable
docker tag myapp:1.0 ghcr.io/acme/myapp:1.0

latest ไม่ใช่ tag วิเศษที่หมายถึง “ใหม่ล่าสุด” เป็นแค่สตริงเริ่มต้นที่ Docker ใช้เมื่อคุณละ tag ไว้ ไม่มีความหมายเชิง semantic version ใด ๆ ถ้าคุณ push myapp:1.0 และ myapp:latest แยกกัน ทั้งสองอาจชี้ไปยัง image layer ที่ต่างกันโดยสิ้นเชิงก็ได้

ใน production pipeline ให้ใช้ tag ที่ชัดเจนและมีความหมายเสมอ (เลขเวอร์ชัน, git SHA, วันที่) เพื่อให้คุณรู้แน่ชัดว่าสิ่งที่ deploy ไปคืออะไร

โดยปริยาย docker build . จะส่งไดเรกทอรีปัจจุบันทั้งหมดของคุณไปยัง daemon — รวมถึง node_modules/, .git/, test fixtures, และ secret ภายในเครื่อง ไฟล์ .dockerignore (syntax เดียวกับ .gitignore) จะกีดกัน path ออกจาก build context ซึ่ง:

  • เร่งความเร็วการ build (มีข้อมูลต้องส่งน้อยลง)
  • ป้องกันการเผลอ COPY secret เข้าไปใน image ของคุณ
.dockerignore
node_modules/
.git/
.env
*.log
dist/
coverage/
Terminal window
# Build with a version tag
docker build -t myapp:1.0 .
# Also tag as latest
docker tag myapp:1.0 myapp:latest
# Inspect the result
docker images myapp

ผลลัพธ์ที่คาดหวัง:

REPOSITORY TAG IMAGE ID CREATED SIZE
myapp 1.0 a3f2b1c9d4e7 1 minute ago 145MB
myapp latest a3f2b1c9d4e7 1 minute ago 145MB
# syntax=docker/dockerfile:1
FROM alpine:3.20
LABEL maintainer="[email protected]"
WORKDIR /app
RUN echo "v1.0" > version.txt
CMD ["cat", "version.txt"]
# --- build, tag, and inspect ---
# docker build -t myapp:1.0 .
# docker tag myapp:1.0 myapp:latest
# docker images myapp
# docker run --rm myapp:1.0
ตัวเลือกBenefitCost
alpine base imageimage เล็ก, pull เร็วใช้ musl libc ทำให้บาง native binary หรือ npm package compile ไม่ผ่านหรือพังตอน runtime
debian/full base imageมี tool ครบ, compatibility กับ glibc สูงimage ใหญ่กว่ามาก, push/pull ช้าลง
  • ลืม pin tag ของ image (ปล่อยให้เป็น latest หรือไม่ใส่ tag เลย) ทำให้ build วันนี้กับพรุ่งนี้ได้ image คนละตัว
  • ไม่มีไฟล์ .dockerignore ทำให้ build context บวมและ build ช้าลง แถมเสี่ยง secret หลุดเข้าไปใน image
  • สั่ง docker build โดยไม่ใส่ -t เลย ได้ image ที่ไม่มีชื่อ ต้องมาไล่หาด้วย image ID ทีหลัง

💡 ตัวอย่างจากของจริง

Docker Hub official image อย่าง node หรือ postgres publish หลาย tag พร้อมกัน (เช่น 22, 22-alpine, 22-slim) และ build แบบ multi-arch (amd64/arm64) เพื่อให้ทีม production เลือก pin tag ที่เหมาะกับงานได้ตรงจุด

build context ใน `docker build .` คืออะไร?
`docker tag myapp:1.0 myapp:stable` ทำอะไร?
จุดประสงค์หลักของไฟล์ .dockerignore คืออะไร?
ข้อความใดเกี่ยวกับ tag `latest` ที่เป็นจริง?