ไฟล์ compose.yaml
มองภาพรวม compose.yaml
หัวข้อที่มีชื่อว่า “มองภาพรวม compose.yaml”ทุก Compose file มี key ระดับบนสุดที่จำเป็นหนึ่งตัว: services ส่วนอื่นๆ — networks, volumes, configs — เป็นตัวเลือก
services: service-name: image: some-image:tag build: . ports: - "hostPort:containerPort" environment: - KEY=value command: ["executable", "arg"]แต่ละ key ภายใต้ services คือชื่อ service ที่คุณเลือกเอง Compose สตาร์ทหนึ่ง container ต่อหนึ่ง service โดยค่าเริ่มต้น
key services
หัวข้อที่มีชื่อว่า “key services”services คือ map แต่ละรายการคือ service ที่มีชื่อ ชื่อนั้นกลายเป็นทั้ง identifier ของ container และ DNS hostname ที่ service อื่นใช้เข้าถึง service นั้นบน network ภายใน
services: api: image: node:22-alpine db: image: postgres:17-alpineที่นี่ api และ db คือสอง service Compose สร้างหนึ่ง container สำหรับแต่ละตัว
image กับ build
หัวข้อที่มีชื่อว่า “image กับ build”ใช้ image เพื่อ pull image สำเร็จรูปจาก registry:
services: web: image: nginx:alpineใช้ build เพื่อสร้าง image จาก Dockerfile ในเครื่องตอน build time:
services: app: build: .คุณสามารถรวมทั้งสองได้ — build บอกว่า Dockerfile อยู่ที่ไหน และ image ตั้งชื่อ image ที่ได้:
services: app: build: . image: myapp:devports map host port ไปยัง container port ในรูปแบบ "host:container" ใส่ quote เสมอเพื่อป้องกัน YAML แปลค่าผิด:
services: web: image: nginx:alpine ports: - "8080:80" - "8443:443"environment
หัวข้อที่มีชื่อว่า “environment”ส่ง environment variables เข้า container แบบ list หรือ mapping:
# แบบ listenvironment: - NODE_ENV=production - PORT=3000
# แบบ mappingenvironment: NODE_ENV: production PORT: "3000"ทั้งสองแบบเทียบเท่ากัน แบบ list คล้าย shell export syntax จึงพบบ่อยกว่า
command
หัวข้อที่มีชื่อว่า “command”Override ค่า CMD เริ่มต้นจาก image:
services: worker: image: myapp:latest command: ["node", "worker.js"]ส่งเป็น string ธรรมดาสำหรับคำสั่งที่ให้ shell ตีความ:
services: worker: image: myapp:latest command: node worker.jsไม่ต้องมี version key อีกแล้ว
หัวข้อที่มีชื่อว่า “ไม่ต้องมี version key อีกแล้ว”tutorial เก่าๆ จะแสดง version: "3.9" ที่ด้านบนของไฟล์ นั่นล้าสมัยแล้ว Compose Specification ไม่ต้องการหรือแนะนำ key version อีกต่อไป tooling รุ่นใหม่ไม่สนใจ key นี้แล้ว ไฟล์ใหม่ไม่ต้องใส่เลย
ตัวอย่างสมบูรณ์
หัวข้อที่มีชื่อว่า “ตัวอย่างสมบูรณ์”services: app: build: . ports: - "3000:3000" environment: - NODE_ENV=production - DATABASE_URL=postgres://db:5432/mydb command: ["node", "src/server.js"] db: image: postgres:17-alpine environment: - POSTGRES_PASSWORD=secretลองปฏิบัติจริง
หัวข้อที่มีชื่อว่า “ลองปฏิบัติจริง”snippet ด้านล่างเขียน compose.yaml สมบูรณ์และสตาร์ทเพื่อตรวจสอบแต่ละ field ในทางปฏิบัติ
# Write a compose.yaml with two services
cat > compose.yaml <<'EOF'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
environment:
- NGINX_HOST=localhost
command: ["nginx", "-g", "daemon off;"]
echo:
image: alpine
command: ["sh", "-c", "echo 'compose.yaml works!' && sleep 30"]
EOF
# Start both services
docker compose up -d
# Show running containers
docker compose ps
# Read echo output
docker compose logs echo
# Clean up
docker compose downข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| Docker Compose | เขียน compose.yaml ไฟล์เดียว รัน local ได้ทันที เหมาะกับ dev loop | รันได้จริงบน host เดียว ไม่มี self-healing ข้าม node |
| Kubernetes | scale และ self-heal ข้ามหลาย node ในคลัสเตอร์ | ต้องเรียนรู้ manifest, controller และ operational overhead ที่สูงกว่ามาก |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- ลืมว่า key
servicesเป็น required key เดียว แล้วพยายามใส่ config ระดับ service ไว้ผิดที่ (เช่นใส่image:ไว้นอก block ของ service) - ใส่
version: "3.9"กลับเข้ามาใน compose.yaml ใหม่เพราะ copy จาก tutorial เก่า ทั้งที่ tooling ปัจจุบันไม่อ่านค่านี้แล้ว - ลืมใส่ quote รอบ port mapping (เช่น
ports: - 8080:80แทนที่จะเป็น"8080:80") ทำให้ YAML parser ตีความ colon ผิดในบางเคส
💡 ตัวอย่างจากของจริง
ทีม dev ที่ Shopify และทีมเล็กจำนวนมากใช้ compose.yaml เดียวกันเป็นจุดเริ่มต้นของทั้ง local dev และ production image — เขียนโครงสร้าง services ให้ถูกต้องตั้งแต่ compose-file แล้วค่อยเอา image เดียวกันไป deploy บน Kubernetes ทีหลัง