Running services
Start all services defined in your workspace:
dagger up
Services run in ephemeral containers. Dagger tunnels their ports to your local machine. Stop with Ctrl+C.
Listing and filtering services
dagger up -l # list available services
dagger up web # start only the 'web' service
dagger up web api redis # start multiple services
Use cases
- Running a database for local development or testing
- Running end-to-end integration tests against a service
- Running sidecars (proxies, caches, queues)
How services work
Service containers have three key properties:
- Content-addressed hostnames. Each service gets a canonical hostname derived from its definition. Same definition, same hostname, so no port conflicts.
- Just-in-time lifecycle. Services start when first needed. If several clients request the same service, they share one instance. Services stop when nothing references them anymore.
- Health checks. Dagger health-checks a service before any client can connect, so there is no race between service startup and test execution.
Wiring a service into another module
Generic modules can compose through workspace settings. If a module's constructor accepts an optional Service, you can wire another module's service into it with a plain module reference. No glue module required.
For example, a docusaurus module knows how to serve a documentation site, and a playwright module knows how to run browser tests against any web app it's given. Connect them in dagger.toml:
[modules.docusaurus]
source = "github.com/example/docusaurus@v1.0"
[modules.playwright]
source = "github.com/example/playwright@v1.0"
[modules.playwright.settings]
app = "docusaurus:serve"
The setting is a <module>:<function> string. The leading segment is a module's install name, the [modules.X] key in the same dagger.toml. The rest names a zero-arg function on it. Any function returning a matching type works, and Dagger injects the value it returns. dagger up -l is a convenient place to find and copy a service's path, but the path is valid because it resolves to a Service, not because the function is listed there. When Dagger constructs playwright, it resolves the reference and passes the service as the app argument.
This also works for Container constructor arguments. Point the setting at any module function that returns a Container, for example to share a common base image across modules.
Because a module reference is an ordinary address string, the same value works as a CLI flag with no dagger.toml entry:
dagger call playwright --app=docusaurus:serve test
Container-to-host networking
A service defined in a module can be exposed to your local machine:
# Start an HTTP service and access it locally
dagger up web
curl http://localhost:80
Host-to-container networking
Containers running in Dagger can also connect to services on your host machine. This is useful for testing against a locally running database or API.
A function exposes a host service by accepting it as an argument, using the tcp:// or udp:// provider to point at a host port:
# Make a database running on the host reachable from the function
dagger api call integration-test --db=tcp://localhost:5432
Inside the function the argument is an ordinary Service, so the same code works whether the upstream runs on your host or in another container.