dagger
Daggerは、TypeScriptなどでCI/CDパイプラインをコードとして記述し、ローカルやCI環境で実行可能な、移植性とキャッシュ効率に優れたコンテナベースのパイプラインを構築するSkill。
📜 元の英語説明(参考)
Write CI/CD pipelines as code with Dagger — portable, cacheable, container-based pipelines that run locally and in any CI system. Use when someone asks to "write CI pipeline in TypeScript", "portable CI/CD", "run GitHub Actions locally", "Dagger pipeline", "CI as code", "containerized build pipeline", or "test my CI locally before pushing". Covers Dagger SDK (TypeScript/Python), pipeline composition, caching, secrets, and multi-stage builds.
🇯🇵 日本人クリエイター向け解説
Daggerは、TypeScriptなどでCI/CDパイプラインをコードとして記述し、ローカルやCI環境で実行可能な、移植性とキャッシュ効率に優れたコンテナベースのパイプラインを構築するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o dagger.zip https://jpskill.com/download/14811.zip && unzip -o dagger.zip && rm dagger.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/14811.zip -OutFile "$d\dagger.zip"; Expand-Archive "$d\dagger.zip" -DestinationPath $d -Force; ri "$d\dagger.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
dagger.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
daggerフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Dagger
概要
Daggerを使用すると、YAMLの代わりにTypeScript、Python、またはGoでCI/CDパイプラインを記述できます。パイプラインはコンテナ内で実行され、完全にキャッシュ可能であり、ラップトップとGitHub Actions/GitLab CI/Jenkinsで同じように動作します。「CIでは動作するがローカルでは動作しない」という問題はもうありません。プッシュする前にパイプライン全体をテストしてください。
どのような時に使うか
- コミットをプッシュしてYAMLベースのCI設定をデバッグすることにうんざりしている
- ローカルとCIでまったく同じパイプラインを実行する必要がある
- TypeScript/Pythonロジック(条件分岐、ループ)の恩恵を受ける複雑なビルドパイプライン
- ビルドステップにコンテナレベルのキャッシュが必要
- 異なるプロジェクトが異なるパイプラインを必要とするマルチ言語モノレポ
手順
セットアップ
# Dagger CLIをインストール (macOS/Linux)
brew install dagger/tap/dagger
# プロジェクトで初期化
dagger init --sdk=typescript
基本的なパイプライン
// dagger/src/index.ts — Node.jsプロジェクトのCIパイプライン
/**
* ビルド、テスト、Dockerイメージを作成するDaggerパイプライン。
* ラップトップと任意のCIシステムで同じように実行されます。
*/
import { dag, Container, Directory, object, func } from "@dagger.io/dagger";
@object()
class Ci {
/**
* 完全なCIパイプラインを実行: install → lint → test → build。
*/
@func()
async ci(source: Directory): Promise<string> {
const node = this.base(source);
// ステップを順番に実行 (それぞれが独立してキャッシュされる)
await this.lint(source);
await this.test(source);
const built = await this.build(source);
return "✅ CI passed";
}
/**
* 依存関係がインストールされたベースコンテナ。
* キャッシュされる — package.jsonが変更された場合にのみ再実行される。
*/
@func()
base(source: Directory): Container {
return dag
.container()
.from("node:20-slim")
.withDirectory("/app", source)
.withWorkdir("/app")
// 実行間でnode_modulesをキャッシュする
.withMountedCache("/app/node_modules", dag.cacheVolume("node-modules"))
.withExec(["npm", "ci"]);
}
@func()
async lint(source: Directory): Promise<string> {
return this.base(source)
.withExec(["npm", "run", "lint"])
.stdout();
}
@func()
async test(source: Directory): Promise<string> {
return this.base(source)
.withExec(["npm", "run", "test", "--", "--run"])
.stdout();
}
@func()
async build(source: Directory): Promise<Directory> {
return this.base(source)
.withExec(["npm", "run", "build"])
.directory("/app/dist");
}
/**
* Dockerイメージをビルドしてプッシュする。
*/
@func()
async publish(source: Directory, registry: string, tag: string): Promise<string> {
const built = await this.build(source);
const image = dag
.container()
.from("node:20-slim")
.withDirectory("/app", built)
.withWorkdir("/app")
.withEntrypoint(["node", "index.js"]);
const ref = await image.publish(`${registry}:${tag}`);
return `📦 Published: ${ref}`;
}
}
ローカルで実行
# ローカルコードで完全なCIパイプラインを実行
dagger call ci --source=.
# テストのみを実行
dagger call test --source=.
# Dockerイメージをビルドして公開
dagger call publish --source=. --registry=ghcr.io/myorg/myapp --tag=latest
サービス(データベース)を使用したパイプライン
// dagger/src/index.ts — 統合テスト用のPostgresを使用したパイプライン
@object()
class Ci {
@func()
async integrationTest(source: Directory): Promise<string> {
// Postgresサービスコンテナを起動
const db = dag
.container()
.from("postgres:16")
.withEnvVariable("POSTGRES_PASSWORD", "test")
.withEnvVariable("POSTGRES_DB", "testdb")
.withExposedPort(5432)
.asService();
// データベースが利用可能な状態でテストを実行
return this.base(source)
.withServiceBinding("db", db)
.withEnvVariable("DATABASE_URL", "postgresql://postgres:test@db:5432/testdb")
.withExec(["npm", "run", "db:migrate"])
.withExec(["npm", "run", "test:integration"])
.stdout();
}
}
シークレット
// シークレットを安全に処理 — コンテナレイヤーに決して焼き付けない
@func()
async deploy(source: Directory, apiKey: Secret): Promise<string> {
return this.base(source)
.withSecretVariable("API_KEY", apiKey) // レイヤー内ではなく、環境変数としてマウントされる
.withExec(["npm", "run", "deploy"])
.stdout();
}
GitHub Actionsとの統合
# .github/workflows/ci.yml — GitHub ActionsでDaggerパイプラインを実行
name: CI
on: [push, pull_request]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dagger/dagger-for-github@v7
with:
verb: call
args: ci --source=.
例
例1:モノレポCIパイプライン
ユーザープロンプト: 「Next.jsフロントエンドとPythonバックエンドを持つモノレポがあります。両方をテストするCIパイプラインをセットアップしてください。」
エージェントは、フロントエンド(Node.jsコンテナ、npm test)とバックエンド(Pythonコンテナ、pytest)用の個別の関数を持つDaggerパイプラインを作成し、両方を共有キャッシュを持つ同じパイプラインから実行します。
例2:GitHub ActionsをDaggerに置き換える
ユーザープロンプト: 「私のGitHub Actionsワークフローは200行のYAMLで、ローカルでテストできません。Daggerに変換してください。」
エージェントは、各YAMLステップをDagger関数に変換し、依存関係のキャッシュを追加し、dagger callを使用して同じパイプラインをローカルで実行する方法を示します。
ガイドライン
- 最初にローカルで実行 — CIにプッシュする前に、ラップトップで
dagger callを実行します - 積極的にキャッシュ — node_modules、pipキャッシュ、ビルド成果物には
withMountedCacheを使用します Secretタイプによるシークレット — シークレットをプレーンな文字列またはDockerfileの環境変数として渡さないでください- データベースのサービス — テストでPostgres/Redisに
asService()+withServiceBinding()を使用します - 各
@func()は独立して呼び出し可能 — 構成可能性を考慮して設計します - コンテナレイヤーはキャッシュされます — 変更が少ないステップが最初に実行されるように操作を順序付けます
- チームキャッシュ用のDagger Cloud — CIランナー間でビルドキャッシュを共有します
- 各コマンドに
withExecを使用 — sep
(原文がここで切り詰められています)
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Dagger
Overview
Dagger lets you write CI/CD pipelines in TypeScript, Python, or Go instead of YAML. Pipelines run in containers, are fully cacheable, and work identically on your laptop and in GitHub Actions/GitLab CI/Jenkins. No more "works in CI but not locally" — test your entire pipeline before pushing.
When to Use
- Tired of debugging YAML-based CI configs by pushing commits
- Need to run the exact same pipeline locally and in CI
- Complex build pipelines that benefit from TypeScript/Python logic (conditionals, loops)
- Want container-level caching for build steps
- Multi-language monorepo where different projects need different pipelines
Instructions
Setup
# Install Dagger CLI (macOS/Linux)
brew install dagger/tap/dagger
# Initialize in your project
dagger init --sdk=typescript
Basic Pipeline
// dagger/src/index.ts — CI pipeline for a Node.js project
/**
* Dagger pipeline that builds, tests, and creates a Docker image.
* Runs identically on your laptop and in any CI system.
*/
import { dag, Container, Directory, object, func } from "@dagger.io/dagger";
@object()
class Ci {
/**
* Run the full CI pipeline: install → lint → test → build.
*/
@func()
async ci(source: Directory): Promise<string> {
const node = this.base(source);
// Run steps in sequence (each cached independently)
await this.lint(source);
await this.test(source);
const built = await this.build(source);
return "✅ CI passed";
}
/**
* Base container with dependencies installed.
* Cached — only re-runs if package.json changes.
*/
@func()
base(source: Directory): Container {
return dag
.container()
.from("node:20-slim")
.withDirectory("/app", source)
.withWorkdir("/app")
// Cache node_modules across runs
.withMountedCache("/app/node_modules", dag.cacheVolume("node-modules"))
.withExec(["npm", "ci"]);
}
@func()
async lint(source: Directory): Promise<string> {
return this.base(source)
.withExec(["npm", "run", "lint"])
.stdout();
}
@func()
async test(source: Directory): Promise<string> {
return this.base(source)
.withExec(["npm", "run", "test", "--", "--run"])
.stdout();
}
@func()
async build(source: Directory): Promise<Directory> {
return this.base(source)
.withExec(["npm", "run", "build"])
.directory("/app/dist");
}
/**
* Build and push a Docker image.
*/
@func()
async publish(source: Directory, registry: string, tag: string): Promise<string> {
const built = await this.build(source);
const image = dag
.container()
.from("node:20-slim")
.withDirectory("/app", built)
.withWorkdir("/app")
.withEntrypoint(["node", "index.js"]);
const ref = await image.publish(`${registry}:${tag}`);
return `📦 Published: ${ref}`;
}
}
Run Locally
# Run the full CI pipeline on your local code
dagger call ci --source=.
# Just run tests
dagger call test --source=.
# Build and publish Docker image
dagger call publish --source=. --registry=ghcr.io/myorg/myapp --tag=latest
Pipeline with Services (Database)
// dagger/src/index.ts — Pipeline with Postgres for integration tests
@object()
class Ci {
@func()
async integrationTest(source: Directory): Promise<string> {
// Start a Postgres service container
const db = dag
.container()
.from("postgres:16")
.withEnvVariable("POSTGRES_PASSWORD", "test")
.withEnvVariable("POSTGRES_DB", "testdb")
.withExposedPort(5432)
.asService();
// Run tests with database available
return this.base(source)
.withServiceBinding("db", db)
.withEnvVariable("DATABASE_URL", "postgresql://postgres:test@db:5432/testdb")
.withExec(["npm", "run", "db:migrate"])
.withExec(["npm", "run", "test:integration"])
.stdout();
}
}
Secrets
// Handle secrets safely — never baked into container layers
@func()
async deploy(source: Directory, apiKey: Secret): Promise<string> {
return this.base(source)
.withSecretVariable("API_KEY", apiKey) // Mounted as env var, not in layer
.withExec(["npm", "run", "deploy"])
.stdout();
}
GitHub Actions Integration
# .github/workflows/ci.yml — Run Dagger pipeline in GitHub Actions
name: CI
on: [push, pull_request]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dagger/dagger-for-github@v7
with:
verb: call
args: ci --source=.
Examples
Example 1: Monorepo CI pipeline
User prompt: "I have a monorepo with a Next.js frontend and a Python backend. Set up a CI pipeline that tests both."
The agent will create a Dagger pipeline with separate functions for frontend (Node.js container, npm test) and backend (Python container, pytest), both running from the same pipeline with shared caching.
Example 2: Replace GitHub Actions with Dagger
User prompt: "My GitHub Actions workflow is 200 lines of YAML and I can't test it locally. Convert it to Dagger."
The agent will translate each YAML step into a Dagger function, add caching for dependencies, and show how to run the same pipeline locally with dagger call.
Guidelines
- Run locally first —
dagger callon your laptop before pushing to CI - Cache aggressively —
withMountedCachefor node_modules, pip cache, build artifacts - Secrets via
Secrettype — never pass secrets as plain strings or env vars in Dockerfiles - Services for databases —
asService()+withServiceBinding()for Postgres/Redis in tests - Each
@func()is independently callable — design for composability - Container layers are cached — order operations so rarely-changing steps come first
- Dagger Cloud for team caching — share build cache across CI runners
- Use
withExecfor each command — separate steps for better cache granularity