Chaining
Function chaining is one of Dagger's most powerful features, as it allows you to dynamically compose complex pipelines by connecting one Dagger Function with another. The following sections demonstrate a few more examples of function chaining with the Dagger CLI.
Execute commands in containers
The Dagger CLI can add follow-up processing to a just-in-time container, essentially enabling you to continue the pipeline directly from the command-line. Container
objects expose a withExec()
API method, which lets you execute a command in the corresponding container.
Here is an example of chaining a Container.withExec()
call to a container returned by a Wolfi container builder Dagger Function, to execute a command that displays the contents of the /etc/
directory:
dagger -m github.com/shykes/daggerverse/wolfi@v0.1.4 call container with-exec --args="ls","/etc/" stdout
Here is an example of chaining a Container.withExec()
function call to a container returned by a Wolfi container builder Dagger Function, to execute a command that displays the contents of the /etc/os-release
file:
dagger -m github.com/shykes/daggerverse/wolfi@v0.1.4 call container with-exec --args="cat","/etc/os-release" stdout
Here is an example of chaining a Container.withExec()
function call to do the reverse: modify a container returned by a Wolfi container builder Dagger Function, by removing the /etc/os-release
file from the container filesysytem:
dagger -m github.com/shykes/daggerverse/wolfi@v0.1.4 call container with-exec --args="rm","/etc/os-release" with-exec --args="ls","/etc" stdout
Here is another example which chains multiple Container.withExec()
calls to install the curl
package in a Wolfi container, send an HTTP request, and return the output:
dagger -m github.com/shykes/daggerverse/wolfi@v0.1.4 call container with-exec --args="apk,add,curl" with-exec --args="curl,-L,dagger.io" stdout
Live-debug container builds
Container
objects expose a terminal()
API method, which lets you starting an ephemeral interactive terminal session in the corresponding container. This feature is very useful for debugging and experimenting since it allows you to inspect containers directly and at any stage of your Dagger Function execution.
Here is an example of chaining a Container.terminal()
function call to start an interactive terminal in the container returned by a Wolfi container builder Dagger Function:
dagger -m github.com/shykes/daggerverse/wolfi@v0.1.4 call container --packages=cowsay terminal
By default, the terminal is started with the sh
shell, although this can be overridden by adding the --cmd
argument. To start the same terminal with the zsh
shell, use:
dagger -m github.com/shykes/daggerverse/wolfi@v0.1.4 call container --packages=cowsay,zsh terminal --cmd=zsh
Export directories, files and containers
Just-in-time artifacts such as containers, directories and files can be exported to the host filesystem from the Dagger Function that produced them. The destination path on the host is specified using the --path
argument.
Here is an example of exporting the directory returned by a Go builder Dagger Function to the ./my-build
directory on the host:
dagger -m github.com/kpenfound/dagger-modules/golang@v0.2.0 call build --source=https://github.com/dagger/dagger --args=./cmd/dagger export --path=./my-build
By default, the Directory.export()
method exports the files that exist in the returned directory to the host, but it does not modify or delete any files that already exist at that host path. To replace the contents of the target host directory, such that it exactly matches the directory being exported, add the --wipe
argument.
Here is an example of exporting the build directory returned by the same Dagger Function above, deleting and replacing files as needed in the ./my-build
directory on the host:
dagger -m github.com/kpenfound/dagger-modules/golang@v0.2.0 call build --source=https://github.com/dagger/dagger --args=./cmd/dagger export --path=./my-build --wipe
Instead of exporting an entire directory, you can also export a file. Here is an example of exporting a single file from the directory returned by the same Go builder Dagger Function, as ./my-binary-file
on the host:
dagger -m github.com/kpenfound/dagger-modules/golang@v0.2.0 call build --source=https://github.com/dagger/dagger --args=./cmd/dagger file --path=dagger export --path=./my-binary-file
Here is another example, this time exporting the results of a ruff
linter Dagger Function as /tmp/report.json
on the host:
dagger -m github.com/dagger/dagger/dev/ruff@a29dadbb5d9968784847a15fccc5629daf2985ae call lint --source https://github.com/dagger/dagger report export --path=/tmp/report.json
Here is an example of exporting a container returned by a Wolfi container builder Dagger Function as an OCI tarball named /tmp/tarball.tar.gz
on the host:
dagger -m github.com/shykes/daggerverse/wolfi@v0.1.4 call container export --path=./tarball.tar.gz
Inspect directories, files and containers
Here is an example of listing the contents of a directory returned by a Dagger Function, by chaining a call to the Directory.entries()
method:
git clone https://github.com/golang/example
dagger -m github.com/kpenfound/dagger-modules/golang@v0.2.0 call build --source=./example/hello --args=. directory --path=. entries
Here is an example of using the File.contents()
method to print the JSON report of a linter run:
dagger call -m github.com/dagger/dagger/dev/ruff@a29dadbb5d9968784847a15fccc5629daf2985ae lint --source https://github.com/dagger/dagger report contents
Similar, the File
object exposes a method to return the size of the corresponding file. Here is an example of obtaining the size of the ZIP file returned by a file archiving Dagger Function, by chaining a call to File.size()
method:
dagger -m github.com/sagikazarmark/daggerverse/arc@40057665476af62e617cc8def9ef5a87735264a9 call archive-directory --name=dagger-cli '--directory=https://github.com/dagger/dagger#main:cmd/dagger' create --format=zip size
Publish containers
Every Container
object exposes a Container.publish()
API method, which publishes the container as a new image to a specified container registry. The registry address is passed to the function using the --address
argument, and the return value is a string referencing the container image address in the registry.
Here is an example of publishing the container returned by a Wolfi container builder Dagger Function to the ttl.sh
registry, by chaining a Container.publish()
call:
dagger -m github.com/shykes/daggerverse/wolfi@v0.1.4 call container publish --address=ttl.sh/my-wolfi
Start containers as services
Every Container
object exposes a Container.asService()
API method, which turns the container into a Service
. These services can then be spun up for use by other Dagger Functions or by clients on the Dagger host by forwarding their ports. This is akin to a "programmable docker-compose".
To start a Service
returned by a Dagger Function and have it forward traffic to a specified address via the host, chain a call to the Service.up()
API method.
Here is an example of starting an NGINX service on host port 80 by chaining calls to Container.asService()
and Service.up()
:
dagger -m github.com/kpenfound/dagger-modules/nginx@v0.1.0 call container as-service up
By default, each port maps to the same port on the host. To specify a different mapping, use the additional --ports
argument with a list of host/service port mappings. To bind ports randomly, use the --random
argument.
To start the same service and map NGINX port 80 to host port 8080, use:
dagger -m github.com/kpenfound/dagger-modules/nginx@v0.1.0 call container as-service up --ports=8080:80
The service can now be accessed on the specified port. For example, in another terminal, execute the following command to receive the default NGINX welcome page:
curl localhost:8080
To start the same service and map NGINX port 80 to a random port on the host, use:
dagger -m github.com/kpenfound/dagger-modules/nginx@v0.1.0 call container as-service up --random
Modify container filesystems
Here is an example of modifying a container by adding the current directory from the host to the container filesysytem at /src
, by chaining a call to the Container.withDirectory()
method:
The example below uploads the entire current directory to the container filesystem. This can take a significant amount of time with large directories. To reduce the time spent on upload, run this example from a directory containing only a few small files.
dagger -m github.com/shykes/daggerverse/wolfi@v0.1.4 call container with-directory --path=/src --directory=. with-exec --args="ls","/src" stdout
Here is an example of passing a host file to a container builder Dagger Function by chaining a call to the Container.withFile()
function:
dagger -m github.com/shykes/daggerverse/wolfi@v0.1.4 call container with-file --path=/README.md --source=./README.md with-exec --args="cat","/README.md" stdout