Running Services
Start all services defined in your workspace:
dagger up
Services run in ephemeral containers. Their ports are tunneled 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 — no port conflicts.
- Just-in-time lifecycle. Services start when first needed, are de-duplicated if multiple clients request the same service, and stop when no longer referenced.
- Health checks. Services are health-checked before clients can connect. No race conditions 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 just a <module>:<function> string: the leading segment is a module's install name — the [modules.X] key in the same dagger.toml — and the rest names a zero-arg function on it. Any function returning a matching type works; the value it returns is injected. For a service, dagger up -l is a convenient place to discover 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 playwright is constructed, Dagger 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 — no dagger.toml entry required:
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.