กุมภาพันธ์ 2026

Dagger: Programmable CI/CD Engine

เขียน Pipeline เป็น Code แทน YAML ซับซ้อน รันได้ทั้ง Local และ CI

เรียนรู้การใช้ Dagger เครื่องมือ CI/CD ที่เปลี่ยนการเขียน pipeline จาก YAML เป็นภาษาโปรแกรมจริง (Go, Python, TypeScript) ลดความซับซ้อน เพิ่มประสิทธิภาพ และรัน pipeline เหมือนกันทั้งบน local และ CI

เวลาอ่านประมาณ 15 นาที
Go
Python
TypeScript
Docker
CI/CD

1. บทนำ: Dagger คืออะไร?

Dagger เป็น programmable CI/CD engine ที่ช่วยให้คุณเขียน pipeline เป็น code ด้วยภาษาโปรแกรมจริง (เช่น Go, Python, TypeScript) แทนที่จะใช้ YAML configuration files ที่มักซับซ้อนและยากต่อการจัดการ

Dagger ถูกสร้างโดยทีมผู้สร้าง Docker (Solomon Hykes) และออกแบบมาเพื่อแก้ปัญหาหลักของ CI/CD แบบดั้งเดิม:

  • "Works on my machine" problem: Pipeline ที่ทำงานบน local ไม่เหมือนกับบน CI server
  • YAML complexity: YAML files ที่ขยายใหญ่ขึ้นและยากต่อการอ่าน/แก้ไข
  • Vendor lock-in: Pipeline ที่ผูกติดกับ CI provider เฉพาะ
  • Slow feedback loop: ต้อง push code ไปที่ remote repository ทุกครั้งเพื่อทดสอบ pipeline

ด้วย Dagger คุณสามารถเขียน pipeline ครั้งเดียวแล้วรันได้ทั้งบน local machine และ CI/CD platform ใดก็ได้ (GitHub Actions, GitLab CI, Jenkins, etc.) โดยใช้ container เป็น execution environment

Programmable Pipelines

เขียน pipeline ด้วยภาษาโปรแกรมจริง ใช้ condition, loop, function reuse ได้เต็มที่

Local & CI Parity

Pipeline เดียวกันรันได้ทั้งบน local machine และ CI server ผลลัพธ์เหมือนกัน

2. สิ่งที่ต้องเตรียม

ก่อนเริ่มใช้งาน Dagger คุณต้องมีสิ่งต่อไปนี้:

พื้นฐานภาษาโปรแกรม

Go, Python, หรือ TypeScript พื้นฐาน (เลือกอย่างน้อย 1 ภาษา)

Docker หรือ Container Runtime

Docker Desktop, Podman, หรือ container runtime อื่นๆ

ระบบปฏิบัติการ

Linux, macOS, หรือ Windows (WSL2 สำหรับ Windows)

ความรู้ CI/CD พื้นฐาน

เข้าใจ concept ของ CI/CD pipelines และ workflow พื้นฐาน

ระดับความยาก: Intermediate

บทความนี้เหมาะสำหรับผู้ที่มีพื้นฐาน DevOps/CI/CD มาบ้างแล้ว ถ้าคุณเพิ่งเริ่มต้นแนะนำให้ศึกษา GitLab CI/CD Fundamentals ก่อน

3. คุณสมบัติเด่นของ Dagger

Core Features

Programmable Pipelines

เขียน pipeline ด้วยภาษาโปรแกรมจริง แทนที่จะใช้ YAML ที่มีข้อจำกัด สามารถใช้ condition, loop, functions, และ abstraction ได้เต็มที่

ตัวอย่าง: ใช้ if-else ใน pipeline
if os == "linux":
    build_linux()
elif os == "windows":
    build_windows()
else:
    build_macos()

Container-Native Execution

ทุก step ใน pipeline ทำงานใน container ที่แยกจากกัน ใช้ Docker/OCI containers เป็น execution environment ทำให้ได้ผลลัพธ์ที่สม่ำเสมอไม่ว่าคุณจะรันที่ไหน

Built-in Caching

Dagger ใช้ BuildKit เป็น engine ด้านล่าง ทำให้มี caching อัตโนมัติสำหรับทุกขั้นตอน ลดเวลา build ซ้ำได้มากถึง 90%

Composable & Reusable

สามารถสร้าง modules และ functions ที่ reuse กันได้ across projects สร้าง library ของ pipeline components สำหรับองค์กร

Architecture ของ Dagger

Dagger Architecture Overview Developer Go/Python/TS Code Dagger CLI dagger run / call Dagger Engine BuildKit + Containers Container Execution Environment Build node:18-alpine Test python:3.11 Deploy docker:latest Developer CLI Interface Execution Engine Containerized Steps

รูปแสดง architecture ของ Dagger: Developer เขียน code → Dagger CLI → Dagger Engine (BuildKit) → Containerized execution

4. เปรียบเทียบ: YAML-based vs Dagger (Code-based)

หัวข้อ Traditional YAML CI/CD Dagger (Code-based)
ภาษา YAML/DSL (จำกัด) Go, Python, TypeScript (เต็มที่)
Local Testing ยาก หรือต้องใช้ tools พิเศษ รัน local ได้เหมือนกับ CI
Reusability Copy-paste หรือ templates Functions, modules, packages
Debugging ยาก ต้องดู logs บน CI Debug ด้วย IDE ได้ local
Vendor Lock-in สูง (GitHub Actions, GitLab CI) ต่ำ (รันได้ทุกที่ที่มี container)
Learning Curve ง่ายเริ่มต้น แต่ซับซ้อนเมื่อใหญ่ เริ่มต้นยากกว่า แต่ scalable ดี

Workflow Comparison

Traditional vs Dagger Workflow Traditional CI/CD (YAML) 1. Write YAML config 2. Push to GitHub 3. CI runs (remote) 4. Debug via logs Dagger (Code-based) 1. Write pipeline code 2. Test locally 3. Same code in CI 4. Debug with IDE Traditional: Push & Pray Dagger: Test Locally First

5. การติดตั้ง Dagger

การติดตั้ง Dagger ทำได้หลายวิธี ขึ้นอยู่กับระบบปฏิบัติการและความต้องการของคุณ

วิธีที่ 1: ติดตั้งบน Ubuntu/Debian

terminal
# Download และติดตั้ง Dagger CLI
curl -L https://dl.dagger.io/dagger/install.sh | DAGGER_VERSION=0.14.0 sh

# เพิ่มไปที่ PATH
sudo mv ./dagger /usr/local/bin/

# ตรวจสอบการติดตั้ง
dagger version

วิธีที่ 2: ใช้ Docker (ไม่ต้องติดตั้ง)

terminal
# รัน Dagger ผ่าน Docker container
docker run --rm -v $(pwd):/work -w /work \
  -v /var/run/docker.sock:/var/run/docker.sock \
  ghcr.io/dagger/dagger:latest \
  dagger version

วิธีที่ 3: ติดตั้งผ่าน Package Manager

Homebrew (macOS)

brew install dagger/tap/dagger

Scoop (Windows)

scoop bucket add dagger
scoop install dagger

ตรวจสอบการติดตั้ง

terminal
$ dagger version
dagger 0.14.0 (v0.14.0)
buildkit v0.15.0

$ dagger --help
Usage: dagger <command>

Available Commands:
  call        Call a function in a module
  config      Manage dagger configuration
  develop     Start a development session
  func        Manage functions
  init        Initialize a new Dagger module
  login       Log in to Dagger Cloud
  project     Manage projects
  run         Run a Dagger pipeline
  shell       Open a shell in a service container
  version     Print Dagger version

6. Tutorial: สร้าง Pipeline แรกของคุณ

ในส่วนนี้เราจะสร้าง simple pipeline สำหรับ build และ test Node.js application

Step 1: Initialize Dagger Project

terminal
# สร้าง directory สำหรับ project
mkdir my-dagger-project
cd my-dagger-project

# Initialize Dagger project (เลือกภาษา)
dagger init --sdk=python
# หรือ
dagger init --sdk=go
# หรือ
dagger init --sdk=typescript

Step 2: เขียน Pipeline (Python Example)

main.py
import dagger
from dagger import dag, function, object_type

@object_type
class MyApp:
    @function
    async def build(self, source: dagger.Directory) -> dagger.Directory:
        """Build Node.js application"""
        return await (
            dag.container()
            .from_("node:18-alpine")
            .with_directory("/src", source)
            .with_workdir("/src")
            .with_exec(["npm", "ci"])
            .with_exec(["npm", "run", "build"])
            .directory("/src/dist")
        )
    
    @function
    async def test(self, source: dagger.Directory) -> str:
        """Run tests"""
        return await (
            dag.container()
            .from_("node:18-alpine")
            .with_directory("/src", source)
            .with_workdir("/src")
            .with_exec(["npm", "ci"])
            .with_exec(["npm", "test"])
            .stdout()
        )
    
    @function
    async def docker_image(self, source: dagger.Directory, tag: str = "latest") -> str:
        """Build Docker image"""
        build_dir = await self.build(source)
        
        return await (
            dag.container()
            .from_("nginx:alpine")
            .with_directory("/usr/share/nginx/html", build_dir)
            .publish(f"myapp:{tag}")
        )

Step 3: รัน Pipeline Locally

terminal
# รัน build function
dagger call build --source=. --progress=plain

# รัน test function
dagger call test --source=.

# Build Docker image
dagger call docker-image --source=. --tag=v1.0.0

Step 4: ตัวอย่างเพิ่มเติม (Go & TypeScript)

Go Example

package main

import (
    "context"
    "dagger.io/dagger"
)

func main() {
    ctx := context.Background()
    client, err := dagger.Connect(ctx)
    if err != nil { panic(err) }
    defer client.Close()
    
    source := client.Host().Directory(".")
    
    node := client.Container().
        From("node:18").
        WithDirectory("/src", source).
        WithWorkdir("/src")
    
    build := node.WithExec([]string{"npm", "run", "build"})
    
    output := build.Directory("./dist")
    _, err = output.Export(ctx, "./dist")
    if err != nil { panic(err) }
}

TypeScript Example

import { connect, Container } from "@dagger.io/dagger";

async function main() {
  const client = await connect();
  
  const source = client.host().directory(".");
  
  const node = client.container()
    .from("node:18")
    .withDirectory("/src", source)
    .withWorkdir("/src");
  
  const build = node.withExec(["npm", "run", "build"]);
  
  const output = build.directory("./dist");
  await output.export("./dist");
  
  await client.close();
}

main();

7. การใช้งาน Dagger ในบริบทไทย

สำหรับทีมพัฒนาและบริษัทเทคโนโลยีในประเทศไทย Dagger สามารถช่วยแก้ปัญหาหลายอย่างที่พบเจอในการทำ CI/CD

💡 ประโยชน์สำหรับทีมไทย

ลดค่าใช้จ่าย CI/CD

ทีมขนาดเล็กในไทยสามารถรัน pipeline บน local ก่อน push ลดจำนวน build ที่ต้องรันบน CI platform ที่คิดเงินตาม minutes

เพิ่ม Productivity ของ Developer

Developer ไทยสามารถ debug pipeline ได้บนเครื่องตัวเอง ไม่ต้องรอ CI queue หรือเสียเวลา push-pray-debug cycle

เหมาะกับ Internet ในไทย

การรัน pipeline local ช่วยลดปัญหาความเร็วอินเทอร์เน็ต โดยเฉพาะเมื่อต้อง download dependencies ขนาดใหญ่หลายครั้ง

🏢 Use Cases สำหรับบริษัทไทย

Startup / SME

  • ลด dependency บน CI providers ราคาแพง
  • Developer คนเดียวดูแลหลาย project ได้ง่ายขึ้น
  • สร้าง reusable pipeline components สำหรับทีม

Enterprise / Banking

  • Security: ควบคุม dependencies และ images กลาง
  • Compliance: Audit pipeline code ได้ง่าย
  • Standardization: ใช้ pipeline templates มาตรฐาน

📊 ตัวอย่างจริง: Thai Tech Company

บริษัท FinTech ไทย ใช้ Dagger เพื่อจัดการ CI/CD pipeline สำหรับ microservices 20+ services:

  • ก่อนใช้ Dagger: แต่ละ service มี GitHub Actions workflow file แยกกัน รวมแล้วกว่า 2,000 บรรทัดของ YAML
  • หลังใช้ Dagger: สร้าง shared Dagger module กลาง ใช้โดยทุก services ลด code ซ้ำซ้อน 80%
  • ผลลัพธ์: Developer สามารถรัน pipeline ทุก service บน local ได้ ลด CI build time จาก 30 นาทีเหลือ 5 นาที
  • Cost savings: ลด CI cost ลง 60% เพราะรันเฉพาะเมื่อจำเป็นจริงๆ

8. Integration กับ Tools อื่นๆ

Dagger ทำงานร่วมกับ CI/CD platforms และ tools อื่นๆ ได้อย่างดี

GitHub Actions

# .github/workflows/dagger.yml
name: Dagger Pipeline
on: [push]

jobs:
  dagger:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dagger/dagger-for-github@v4
        with:
          version: 0.14.0
      - run: dagger call build
      - run: dagger call test

GitLab CI

# .gitlab-ci.yml
image: docker:latest

services:
  - docker:dind

stages:
  - dagger

dagger:
  stage: dagger
  script:
    - apk add curl
    - curl -L https://dl.dagger.io/dagger/install.sh | sh
    - ./dagger version
    - ./dagger call build
    - ./dagger call test

Jenkins

// Jenkinsfile
pipeline {
    agent { docker { image 'docker:latest' } }
    
    stages {
        stage('Dagger') {
            steps {
                sh '''
                curl -L https://dl.dagger.io/dagger/install.sh | sh
                ./dagger call build
                ./dagger call test
                '''
            }
        }
    }
}

Daggerverse: Ecosystem ของ Modules

Daggerverse เป็น registry สำหรับ Dagger modules ที่ community สร้างขึ้น คุณสามารถค้นหาและใช้งาน modules สำเร็จรูปได้:

Popular Dagger Modules

Node.js Builder

Build, test, package Node.js apps

Python Package

Build Python wheels and packages

Docker Multi-arch

Build multi-architecture Docker images

Kubernetes Deploy

Deploy to Kubernetes clusters

9. Best Practices & Troubleshooting

✅ Best Practices สำหรับการใช้ Dagger

1. เริ่มจาก Simple Pipeline

เริ่มจาก pipeline ง่ายๆ ก่อน เช่น build และ test เท่านั้น ค่อยๆ เพิ่ม complexity ตามความต้องการ

2. ใช้ Caching ให้เกิดประโยชน์

Dagger มี built-in caching ผ่าน BuildKit ตรวจสอบว่าคุณใช้ directory และ file caching ถูกต้อง

# ใช้ directory caching สำหรับ dependencies
.with_mounted_cache("/src/node_modules", 
    dag.cache_volume("node-modules"))

3. สร้าง Reusable Modules

แยก logic ที่ใช้บ่อยๆ ออกเป็น modules และ functions เพื่อ reuse ระหว่าง projects

4. ใช้ Environment Variables สำหรับ Secrets

อย่า hardcode secrets ใน code ใช้ Dagger's secret management หรือ environment variables

# ใช้ secrets
.with_secret_variable("DOCKER_PASSWORD", 
    dag.set_secret("docker-pass", "..."))

5. Test Pipeline Locally ก่อน Push

ใช้ `dagger call` ทดสอบ pipeline บน local machine ให้แน่ใจว่าทำงานก่อน push ไปยัง CI

🔧 Troubleshooting ปัญหาที่พบบ่อย

Error: "docker daemon not running"

Dagger ต้องการ Docker daemon (หรือ container runtime) ตรวจสอบว่า Docker ทำงานอยู่:

# ตรวจสอบ Docker
docker ps
# หากไม่ได้ ให้ start Docker
sudo systemctl start docker

Error: "buildkitd not running"

Dagger ใช้ BuildKit เป็น engine อาจต้อง start buildkitd ก่อน:

# Start buildkitd
docker run -d --name buildkitd --privileged \
  moby/buildkit:latest

# หรือให้ Dagger จัดการเอง (recommended)
export DAGGER_HOST=docker-container://buildkitd

Performance: Build ช้า

ตรวจสอบว่าคุณใช้ caching ถูกต้อง และพิจารณาใช้ Dagger Cloud สำหรับ remote caching

Debugging: ดู Logs

ใช้ `--progress=plain` เพื่อดู detailed logs:

dagger call build --progress=plain

10. คำถามที่พบบ่อย (FAQ)

Dagger แทนที่ CI/CD tools อื่นๆ ได้ไหม?

Dagger ไม่ได้ replace CI/CD platforms (เช่น GitHub Actions, GitLab CI) แต่ทำงานร่วมกันได้ Dagger ช่วยให้คุณเขียน pipeline logic ที่ portable ระหว่าง CI platforms ต่าง ๆ

ต้องเรียนรู้ภาษาโปรแกรมใหม่ไหม?

คุณสามารถเลือกภาษาโปรแกรมที่คุณถนัดจาก Go, Python, หรือ TypeScript ไม่จำเป็นต้องเรียนรู้ทั้งสามภาษา

Dagger ใช้กับ Kubernetes ได้ไหม?

ได้ Dagger มี modules สำหรับ deploy ไปยัง Kubernetes และสามารถรันบน Kubernetes cluster ได้ (ใช้ Dagger Engine ใน container)

Dagger ฟรีหรือมีค่าใช้จ่าย?

Dagger core engine เปิด source ฟรี Dagger Cloud (remote caching, analytics) มีทั้งฟรีและ paid plans

Team ในไทยมีคนใช้ Dagger ไหม?

ยังมีผู้ใช้ไม่มากในไทย แต่กำลังเติบโต ส่วนใหญ่เป็น tech startups และ teams ที่ทำงานกับ multinational companies คุณสามารถ join Dagger community บน Discord หรือ GitHub

เมื่อไหร่ควรใช้ Dagger vs YAML?

ใช้ Dagger เมื่อ: มี pipeline ซับซ้อน, ต้องการรัน local, มีหลาย projects ที่แชร์ logic, ต้องการลด vendor lock-in ใช้ YAML เมื่อ: pipeline ง่ายๆ, ทีมไม่คุ้นกับ programming, ใช้กับ CI platform เฉพาะที่รองรับดีอยู่แล้ว

11. สรุปและขั้นตอนต่อไป

Dagger เป็นเครื่องมือที่มีแนวคิดใหม่สำหรับการทำ CI/CD โดยเปลี่ยนจากการเขียน YAML configuration เป็นการเขียน pipeline logic ด้วยภาษาโปรแกรมจริง ซึ่งให้ประโยชน์หลายด้านสำหรับทีมพัฒนา

🎯 Key Takeaways

  • Programmable pipelines: เขียน CI/CD logic ด้วย Go, Python, หรือ TypeScript แทน YAML
  • Local & CI parity: รัน pipeline เดียวกันได้ทั้งบน local และ CI server
  • Container-native: ใช้ container เป็น execution environment สำหรับแต่ละ step
  • Portable: Pipeline ทำงานได้กับทุก CI platform ที่รัน container ได้
  • Composable: สร้าง reusable modules และ functions สำหรับองค์กร

🚀 ต่อไปทำอะไร?

สำหรับผู้เริ่มต้น

  • ติดตั้ง Dagger และลองรัน quickstart example
  • แปลง pipeline YAML เดิมเป็น Dagger code
  • ทดลองสร้าง simple build-test pipeline

สำหรับทีม/องค์กร

  • ประเมิน pipeline ที่ซับซ้อนที่สุดสำหรับ migration
  • สร้าง shared Dagger modules สำหรับทีม
  • Integrate กับ CI platform ที่ใช้อยู่
พร้อมเริ่มใช้ Dagger แล้วหรือยัง?

ลองติดตั้ง Dagger วันนี้และเริ่มแปลง pipeline แรกของคุณจาก YAML เป็น code ลดความซับซ้อน เพิ่ม productivity และทำให้ CI/CD workflow ดีขึ้น