ข้ามไปเนื้อหาหลัก
คอนเทนเนอร์· ~25 นาที

MinIO — Object Storage แบบ S3 ในเครื่องเรา

รู้จัก object storage รัน MinIO ด้วย compose แล้วให้ API เก็บไฟล์ลง bucket

พื้นฐานที่ควรรู้: ตอนนี้ไฟล์อัปโหลดกองอยู่ใน /tmp ของ container ซึ่งหายทันทีที่ container ตาย และ Pod อื่น (เช่น Job แปลงไฟล์) มองไม่เห็น — ระบบจริงจึงเก็บวิดีโอใน object storage ที่ทุก service เข้าถึงได้ผ่าน network เราใช้ MinIO ซึ่งพูด protocol เดียวกับ AWS S3 เป๊ะ (ย้ายขึ้น S3 จริงได้โดยแก้ endpoint บรรทัดเดียว)

ตู้ล็อกเกอร์กลางของหมู่บ้าน

Object storage เหมือนตู้ล็อกเกอร์กลาง — ทุกบ้าน (Pod) เอาของมาฝาก/มาหยิบได้ด้วยกุญแจ (access key) และชื่อช่อง (bucket/key เช่น uploads/a1b2c3d4/source.mp4) ไม่ต้องส่งของถึงบ้านกันเอง · ต่างจาก disk ติดเครื่อง (PVC) ที่ผูกกับ Pod ใด Pod หนึ่ง

รัน MinIO + API คู่กันด้วย Docker Compose

services:
  minio:
    image: minio/minio
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: admin
      MINIO_ROOT_PASSWORD: password123
    ports:
      - "9000:9000"   # S3 API
      - "9001:9001"   # เว็บ console
    volumes:
      - minio-data:/data

  api:
    build: ./api
    environment:
      MINIO_HOST: minio      # ← ชื่อ service ใน compose ใช้เป็น hostname ได้เลย
      MINIO_USER: admin
      MINIO_PASS: password123
    ports:
      - "3000:3000"
    depends_on:
      - minio

volumes:
  minio-data:
📄 docker-compose.yaml (วางที่ root โปรเจกต์)

ต่อ API เข้า MinIO

cd ~/projects/k8s-video-pipeline/api
npm install minio
💻 ติดตั้ง MinIO client library
const Minio = require('minio')

const minio = new Minio.Client({
  endPoint: process.env.MINIO_HOST || 'localhost',
  port: parseInt(process.env.MINIO_PORT || '9000'),
  useSSL: false,
  accessKey: process.env.MINIO_USER,
  secretKey: process.env.MINIO_PASS,
})

// สร้าง bucket ที่ต้องใช้ตอนแอปสตาร์ท (idempotent — มีอยู่แล้วก็ข้าม)
async function ensureBuckets() {
  for (const b of ['uploads', 'vod']) {
    if (!(await minio.bucketExists(b))) {
      await minio.makeBucket(b)
      console.log('สร้าง bucket:', b)
    }
  }
}
ensureBuckets().catch((err) => {
  console.error('ต่อ MinIO ไม่ได้:', err.message)
  process.exit(1)
})

// แก้ handler อัปโหลดให้เก็บไฟล์ลง MinIO
app.post('/api/upload', upload.single('video'), async (req, res) => {
  if (!req.file) {
    return res.status(400).json({ error: 'ต้องแนบไฟล์ใน field ชื่อ "video"' })
  }
  const videoId = crypto.randomUUID().slice(0, 8)
  await minio.fPutObject('uploads', videoId + '/source.mp4', req.file.path)
  console.log('เก็บต้นฉบับแล้ว: uploads/' + videoId + '/source.mp4')
  res.json({ videoId, status: 'uploaded' })
})
📄 api/server.js — เวอร์ชัน 2: เพิ่มส่วน MinIO (เพิ่มไว้เหนือ app.post แล้วแก้ handler)
cd ~/projects/k8s-video-pipeline
docker compose up --build

# terminal อื่น
curl -F "video=@sample.mp4" http://localhost:3000/api/upload
# → {"videoId":"...","status":"uploaded"}
💻 รันทั้งคู่แล้วทดสอบ

เปิดเว็บ console ของ MinIO ที่ http://localhost:9001 (user admin / pass password123) → เข้า bucket uploads → ต้องเห็นโฟลเดอร์ videoId ที่มี source.mp4 อยู่ข้างใน — เห็นไฟล์ = ชั้นนี้ผ่าน

สรุป Key Takeaways

  • Object storage = ที่เก็บไฟล์กลางที่ทุก Pod เข้าถึงผ่าน network — MinIO พูด S3 API เป๊ะ
  • bucket uploads เก็บต้นฉบับ · bucket vod เก็บผลลัพธ์ HLS
  • อ่าน config จาก env var ตั้งแต่แรก → ย้ายจาก compose ขึ้น K8s ได้โดยไม่แก้โค้ด
อ่านจบแล้วอย่าลืมทำเครื่องหมาย