開発ツール15分で読める

Dagger——Docker創業者が挑むCI/CDの「Write Once, Run Anywhere」

「CI/CDパイプラインを書き直すのは、もうごめんだ」——GitHub ActionsからGitLab CIへ、JenkinsからCircleCIへ。CI/CDプラットフォームを変えるたびに、パイプラインの定義ファイルを一から書き直す。この「CI/CDベンダーロックイン」問題に、Docker創業者のSolomon Hykesが解決策を提示している。

Daggerは、CI/CDパイプラインをGo、Python、TypeScriptなどのプログラミング言語で記述し、コンテナ内で実行するフレームワークだ。パイプラインの定義がYAMLではなくコードであるため、ローカルでもCI/CDサービス上でも全く同じ動作が保証される。2026年3月時点でDagger 1.x系がリリースされ、シリーズBで$30M(約45億円)の資金調達を完了、エンタープライズ採用が本格化している。

CI/CDの何が問題なのか

YAML地獄とプラットフォーム依存

現代のCI/CDの最大の問題は、パイプライン定義がプラットフォーム固有であることだ。

以下の図は、従来のCI/CDとDaggerのアプローチの違いを示しています。

従来のCI/CD(プラットフォーム依存のYAML)とDagger(コンテナネイティブ・ポータブル)の比較

同じ「ビルド → テスト → デプロイ」のパイプラインを構築するのに、GitHub ActionsではYAML、JenkinsではGroovy、GitLab CIではまた別のYAML構文で記述する必要がある。さらに深刻な問題がある。

  • ローカル再現性ゼロ: CI/CDで失敗したパイプラインをローカルで再現・デバッグできない。「Push → CI失敗 → 修正 → Push → CI失敗...」のフィードバックループが長い
  • テスト不能: YAMLで記述されたパイプラインにはユニットテストを書けない
  • コードの再利用困難: 関数、クラス、パッケージといったプログラミングの基本概念が使えない
  • Secret管理の分散: CI/CDプラットフォームごとにシークレット管理が異なる

「Works on my CI」問題

ローカル開発環境では動くのにCIでは動かない(またはその逆)。この問題の根本原因は、CI/CD環境とローカル環境が全く異なる実行環境であることだ。

Daggerの仕組み

コアコンセプト

Daggerは3つの要素で構成される。

  1. Dagger Engine: BuildKit(Dockerのビルドエンジン)をベースにした実行環境。すべてのパイプラインステップがコンテナ内で実行される
  2. Dagger SDKs: Go、Python、TypeScript、Elixir、PHP、Java等のSDK。パイプラインをネイティブコードで記述
  3. Dagger Cloud: パイプラインの可視化、キャッシング、チームコラボレーション(オプション)

コード例:TypeScript

import { connect } from "@dagger.io/dagger"

connect(async (client) => {
  // ソースコードをロード
  const source = client.host().directory(".", {
    exclude: ["node_modules", ".git"]
  })

  // Node.js コンテナでビルド
  const runner = client
    .container()
    .from("node:20-slim")
    .withDirectory("/app", source)
    .withWorkdir("/app")
    .withExec(["npm", "ci"])
    .withExec(["npm", "run", "build"])
    .withExec(["npm", "test"])

  // テスト結果を取得
  const result = await runner.stdout()
  console.log(result)

  // Dockerイメージとしてエクスポート
  await runner
    .withEntrypoint(["node", "dist/index.js"])
    .publish("registry.example.com/my-app:latest")
})

このコードは以下の特徴を持つ。

  • ローカルで dagger run node pipeline.ts で実行可能: CI/CDプラットフォーム不要
  • GitHub Actionsでも同じコードを呼び出すだけ: run: dagger run node pipeline.ts
  • テスト可能: TypeScriptの通常のテストフレームワークでパイプラインロジックをテスト可能
  • 型安全: SDKの型定義により、誤った設定がコンパイル時に検出される

Dagger Functions(Dagger Modules)

Dagger 1.x系で導入されたDagger Functionsは、パイプラインのステップを再利用可能な関数として定義・公開する仕組みだ。

// Go で Dagger Function を定義
package main

import "dagger.io/dagger"

type MyPipeline struct{}

// ビルド関数
func (m *MyPipeline) Build(ctx context.Context, source *dagger.Directory) *dagger.Container {
    return dag.Container().
        From("golang:1.22").
        WithDirectory("/src", source).
        WithWorkdir("/src").
        WithExec([]string{"go", "build", "-o", "/app", "."})
}

// テスト関数
func (m *MyPipeline) Test(ctx context.Context, source *dagger.Directory) (string, error) {
    return m.Build(ctx, source).
        WithExec([]string{"go", "test", "./..."}).
        Stdout(ctx)
}

Dagger FunctionsはDaggerverse(Dagger版のnpmレジストリ)で公開・共有でき、他のプロジェクトからdagger callで直接呼び出せる。

CI/CDツール比較

以下の図は、主要CI/CDツールをポータビリティとローカル実行可能性で分類しています。

CI/CDツール比較マトリクス。Daggerがポータビリティ・ローカル実行の両面で優位

項目DaggerGitHub ActionsGitLab CIJenkinsTekton
パイプライン定義Go/Python/TSYAMLYAMLGroovyYAML
ローカル実行○(完全)△(actで部分的)
ポータビリティ○(完全)✗(GH依存)✗(GL依存)△(K8s依存)
テスト可能性○(ユニットテスト)
デバッグ○(ブレークポイント)✗(ログのみ)✗(ログのみ)
キャッシング○(BuildKitレイヤー)○(actions/cache)
エコシステムDaggerverseActions MarketplaceTemplatesプラグインHub
学習コスト中(SDK学習)
料金OSS無料 + Cloud有料無料枠あり無料枠あり無料(自前運用)無料(K8s必要)

GitHub Copilotとの相性

DaggerパイプラインはプログラミングSDKで書くため、GitHub CopilotなどのAIコーディングアシスタントとの相性が非常に良い。YAMLのCI/CD定義ではAI補完の精度が低いが、Go/Python/TypeScriptのDagger SDKコードでは高品質な補完が得られる。

実践:GitHub ActionsからDaggerへの移行

Step 1: 既存のGitHub Actions Workflow

# .github/workflows/ci.yml(移行前)
name: CI
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npm run build
      - run: npm test
      - uses: docker/build-push-action@v5
        with:
          push: true
          tags: ghcr.io/my-org/my-app:latest

Step 2: Daggerパイプラインに変換

// ci/pipeline.ts
import { connect } from "@dagger.io/dagger"

connect(async (client) => {
  const source = client.host().directory(".")

  const app = client.container()
    .from("node:20-slim")
    .withDirectory("/app", source)
    .withWorkdir("/app")
    .withExec(["npm", "ci"])
    .withExec(["npm", "run", "build"])
    .withExec(["npm", "test"])

  // <AffiliateLink id="docker">Docker</AffiliateLink>イメージをビルド&プッシュ
  await app
    .withEntrypoint(["node", "dist/index.js"])
    .publish("ghcr.io/my-org/my-app:latest")
})

Step 3: GitHub Actionsから呼び出し

# .github/workflows/ci.yml(移行後)
name: CI
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dagger/dagger-for-github@v6
        with:
          verb: run
          args: node ci/pipeline.ts

GitHub ActionsのワークフローはDaggerを呼び出すだけの薄いラッパーになる。パイプラインのロジックはDaggerコード側に集約され、ローカルでもdagger run node ci/pipeline.tsで同じ動作を確認できる。

日本ではどうなるか

採用状況

日本でのDagger採用はまだ初期段階だが、以下の理由で今後の成長が見込まれる。

  • Docker Compose文化との親和性: 日本の開発現場ではDocker Composeが広く普及しており、「パイプラインもコンテナで動かす」Daggerのコンセプトは受け入れやすい
  • YAML疲れ: GitHub Actions + ArgoCD + Helm + Kustomizeと、YAML定義ファイルの爆発的増加に多くの日本企業が悩んでいる
  • ローカルファースト: 「CIに push してみないとわからない」問題は日本の開発者からも頻繁に不満として挙がる

導入障壁

  • SDK学習コスト: YAMLに慣れたSREチームにとって、Go/Python/TypeScriptでパイプラインを書くことへの心理的ハードルがある
  • 日本語ドキュメントの不足: Daggerのドキュメントは英語のみ
  • エンタープライズ導入実績: 日本の大企業での導入事例がまだほとんど公開されていない

コミュニティ

DaggerはDiscordコミュニティが活発で、日本語チャンネルも存在する。Solomon Hykes自身がコミュニティに積極的に参加しており、質問への回答も早い。

まとめ:Dagger導入のアクションステップ

CI/CDの「Write Once, Run Anywhere」を実現するDaggerは、特にマルチCI/CD環境やローカルデバッグに課題を抱えるチームに強く推奨できる。

  1. ローカルで試す: brew install dagger でインストールし、既存プロジェクトで dagger init を実行。10分で最初のパイプラインが動く
  2. 最も痛い問題から始める: 「CIでしか再現しないバグ」「CI/CD設定の変更がPRレビューしにくい」など、現在のCI/CDの最大の課題をDaggerで解決する
  3. 既存CI/CDとの共存: Daggerは既存のGitHub Actions/GitLab CIを置き換えるのではなく、その中から呼び出される。段階的な移行が可能
  4. Daggerverseの活用: コミュニティが公開しているDagger Functionsを活用し、車輪の再発明を避ける
  5. チームへの展開: パイプラインが「コード」になることで、コードレビュー、テスト、リファクタリングのプラクティスがCI/CDにも適用できることをチームに共有する

Solomon Hykesがかつてコンテナで「アプリケーションのポータビリティ」を実現したように、Daggerで「CI/CDのポータビリティ」を実現しようとしている。CI/CDの進化を追うエンジニアにとって、Daggerは必ずウォッチすべきプロジェクトだ。

この記事をシェア