YAML pipelines are configuration pretending to be code. Dagger lets you write CI/CD pipelines in actual programming languages — Go, Python, TypeScript — with type checking, IDE support, and local execution.
The YAML Problem
Every CI system invented its own YAML dialect:
# GitHub Actions
- run: echo "hello"
# GitLab CI
script: echo "hello"
# CircleCI
- run: echo "hello"
# Azure Pipelines
- script: echo "hello"Same operation, four syntaxes. None of them have type checking, autocompletion, or debuggers. You test YAML pipelines by pushing commits and waiting.
How Dagger Works
Dagger runs your pipeline inside containers, orchestrated by a GraphQL API. You write pipeline logic in a real language:
# ci/main.py
import dagger
async def test():
async with dagger.Connection() as client:
src = client.host().directory(".")
result = await (
client.container()
.from_("python:3.12")
.with_directory("/app", src)
.with_workdir("/app")
.with_exec(["pip", "install", "-r", "requirements.txt"])
.with_exec(["pytest", "tests/"])
.stdout()
)
print(result)# Run locally — same as CI
dagger run python ci/main.pyThe pipeline runs identically on your laptop and in CI. No "push and pray."
Master this topic with hands-on labs
Go beyond reading — build real projects in sandboxed environments with expert video guidance.
Browse Courses →Dagger vs YAML Pipelines
| Feature | YAML Pipelines | Dagger |
|---|---|---|
| Language | YAML dialect | Go, Python, TS |
| Type checking | No | Yes |
| IDE support | Syntax highlighting only | Full (autocomplete, docs) |
| Local execution | Partial (act for GH Actions) | Full, identical to CI |
| Debugging | Print statements, re-run | Breakpoints, local execution |
| Vendor lock-in | High (CI-specific syntax) | Low (runs anywhere) |
| Caching | CI-specific | Content-addressed, automatic |
Composable Pipelines
Dagger functions are composable. Build complex pipelines from reusable pieces:
// ci/main.go
package main
import (
"context"
"dagger/ci/internal/dagger"
)
type Ci struct{}
func (c *Ci) Build(ctx context.Context, src *dagger.Directory) *dagger.Container {
return dag.Container().
From("golang:1.22").
WithDirectory("/app", src).
WithWorkdir("/app").
WithExec([]string{"go", "build", "-o", "app", "."})
}
func (c *Ci) Test(ctx context.Context, src *dagger.Directory) (string, error) {
return c.Build(ctx, src).
WithExec([]string{"go", "test", "./..."}).
Stdout(ctx)
}
func (c *Ci) Lint(ctx context.Context, src *dagger.Directory) (string, error) {
return dag.Container().
From("golangci/golangci-lint:latest").
WithDirectory("/app", src).
WithWorkdir("/app").
WithExec([]string{"golangci-lint", "run"}).
Stdout(ctx)
}Call these functions from any CI system:
# GitHub Actions — just calls Dagger
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dagger/dagger-for-github@v6
with:
verb: call
args: test --src .The pipeline logic lives in your repo, not in your CI provider's configuration.
Get weekly IT automation tips
Docker, Ansible, Terraform, MLOps — curated insights delivered to your inbox. No spam.
Subscribe Free →Content-Addressed Caching
Dagger caches every operation by its inputs. If the source code has not changed, go build uses the cached result. This works across runs and across machines — no manual cache key management.
When to Adopt Dagger
Good fit: - Teams frustrated with YAML pipeline debugging - Organizations using multiple CI providers - Complex pipelines with shared logic across repos - Teams that want to test CI locally before pushing
Not yet ideal: - Simple pipelines (10 lines of YAML is fine) - Teams without Go/Python/TypeScript experience - Organizations deeply invested in a single CI provider's ecosystem
Start by converting your most painful pipeline — the one with 500 lines of YAML and 20-minute debug cycles. That is where Dagger's value is most obvious.
---
Ready to go deeper? Learn CI/CD automation with hands-on courses at CopyPasteLearn.
Ready to learn by doing?
Stop reading tutorials — start building. Expert video courses with hands-on labs in real sandboxed environments.
Related Articles
Woodpecker CI Self-Hosted Pipelines
Woodpecker CI is a lightweight, container-native CI/CD system you can self-host. Learn how Woodpecker compares to Drone, GitHub Actions, and GitLab CI.
Tekton Cloud Native CI/CD
Tekton runs CI/CD pipelines as Kubernetes custom resources. Learn how Tekton works, how to build pipelines with Tasks and Pipelines, and when to choose it.
Earthly Reproducible Build Tool
Earthly combines Dockerfiles and Makefiles into reproducible, containerized builds. Learn how Earthly works, how to write Earthfiles, and when it replaces.
Data Sovereignty Infrastructure
Implement data sovereignty with multi-region cloud infrastructure, GDPR compliance patterns, and geopatriation strategies for regulated workloads.
Debian 13 Trixie: Rock-Solid Linux
Debian 13 Trixie brings stability and reliability that enterprise servers demand. Learn why Debian remains the foundation of the Linux ecosystem.
DevContainers for Team Development
Dev Containers standardize development environments using Docker. Learn how to set up devcontainers for your team with VS Code, GitHub Codespaces, and custom.
Explore topics
Browse more articles on the topics covered here.