Run Pipelines from the Command Line
Introduction​
This tutorial teaches you the basics of using Dagger from the command line. You will learn how to:
- Install the Dagger CLI
- Create a shell script to build an application from a Git repository using the Dagger CLI
Requirements​
This tutorial assumes that:
- You have a basic understanding of shell scripting with Bash. If not, read the Bash reference manual.
- You have Bash installed in your development environment. Bash is available for Linux, Windows and macOS.
- You have the
jq
JSON processor installed in your development environment. If not, download and installjq
. - You have Docker installed and running on the host system. If not, install Docker.
Step 1: Install the Dagger CLI​
The dagger
CLI is available for installation on macOS, Linux, and Windows to run locally or in a CI environment.
Install the dagger
CLI following the steps below.
Step 2: Create a Dagger client in Bash​
The Dagger CLI offers a dagger query
sub-command, which provides an easy way to send API queries to the Dagger Engine from the command line.
To see this in action, create a new shell script named build.sh
and add the following code to it:
#!/bin/bash
alpine=$(dagger query <<EOF | jq -r .container.from.withExec.stdout
{
container {
from(address:"alpine:latest") {
withExec(args:["uname", "-nrio"]) {
stdout
}
}
}
}
EOF
)
echo $alpine
This script invokes the Dagger CLI's query
sub-command and passes it a GraphQL API query. This query performs the following operations:
- It requests the
from
field of Dagger'sContainer
object type, passing it the address of a container image. To resolve this, Dagger will initialize a container using the specified image and return aContainer
object representing thealpine:latest
container image. - Next, it requests the
withExec
field of theContainer
object from the previous step, passing theuname -a
command to the field as an array of arguments. To resolve this, Dagger will return aContainer
object containing the execution plan. - Finally, it requests the
stdout
field of theContainer
object returned in the previous step. To resolve this, Dagger will execute the command and return aString
containing the results. - The result of the query is returned as a JSON object. This object is processed with
jq
and the result string is printed to the console.
Add the executable bit to the shell script and then run the script by executing the commands below:
chmod +x ./build.sh
./build.sh
The script outputs a string similar to the one below.
Linux buildkitsandbox 5.15.0-53-generic #59-Ubuntu SMP Mon Oct 17 18:53:30 UTC 2022 x86_64 Linux
Step 3: Build an application from a remote Git repository​
Now that the shell script is functional, the next step is to flesh it out to actually build an application. This tutorial demonstrates the process by cloning the canonical Git repository for Go and building the "Hello, world" example program from it using the Dagger CLI.
Replace the build.sh
file from the previous step with the version below (highlighted lines indicate changes):
#!/bin/bash
# get Go examples source code repository
source=$(dagger query <<EOF | jq -r .git.branch.tree.id
{
git(url:"https://go.googlesource.com/example") {
branch(name:"master") {
tree {
id
}
}
}
}
EOF
)
# mount source code repository in golang container
# build Go binary
# export binary from container to host filesystem
build=$(dagger query <<EOF | jq -r .container.from.withMountedDirectory.withWorkdir.withExec.file.export
{
container {
from(address:"golang:latest") {
withMountedDirectory(path:"/src", source:"$source") {
withWorkdir(path:"/src") {
withExec(args:["go", "build", "-o", "dagger-builds-hello", "./hello/hello.go"]) {
file(path:"./dagger-builds-hello") {
export(path:"./dagger-builds-hello")
}
}
}
}
}
}
}
EOF
)
# check build result and display message
if [ "$build" == "true" ]
then
echo "Build successful"
else
echo "Build unsuccessful"
fi
This revision of the script contains two queries stitched together.
The first query:
- requests the
master
branch of the Git source code repository (returned as aGitRef
object); - requests the filesystem of that branch (returned as a
Directory
object); - requests the content-addressed identifier of that
Directory
(returned as a base64-encoded value and interpolated into the second query).
The second query:
- initializes a new
alpine:latest
container (returned as aContainer
object); - mounts the
Directory
from the first query within the container filesystem at the/src
mount point (returned as a revisedContainer
); - sets the working directory within the container to the mounted filesystem (returned as a revised
Container
); - requests execution of the
go build
command (returned as a revisedContainer
containing the execution plan); - retrieves the build artifact (returned as a
File
); - writes the
File
from the container to the host as a binary file nameddagger-builds-hello
.
The return value of the final export
field is a Boolean value indicating whether the file was successfully written to the host or not. This value is extracted from the GraphQL API response document using jq
and evaluated with Bash.
Run the shell script by executing the command below:
./build.sh
As described above, the script retrieves the source code repository, mounts and builds it in a container, and writes the resulting binary file to the host. At the end of the process, the built Go application is available in the working directory on the host, as shown below:
tree
.
├── build.sh
└── dagger-builds-hello
Conclusion​
This tutorial introduced you to the Dagger CLI and its dagger query
sub-command. It explained how to install the CLI and how to use it to execute Dagger GraphQL API queries. It also provided a working example of how to run a Dagger pipeline from the command line using a Bash shell script.
Use the API Reference and the CLI Reference to learn more about the Dagger GraphQL API and the Dagger CLI respectively.