Skip to main content

Arguments

Dagger Functions, just like regular functions, can accept arguments. In addition to basic types (string, boolean, integer, arrays...), Dagger also defines powerful core types which Dagger Functions can use for their arguments, such as Directory, Container, Service, Secret, and many more.

When calling a Dagger Function from the CLI, its arguments are exposed as command-line flags. How the flag is interpreted depends on the argument type.

important

Dagger Functions execute in containers and thus do not have default access to your host environment (host files, directories, environment variables, etc.). Access to these host resources can only be granted by explicitly passing them as argument values to the Dagger Function.

  • Files and directories: Dagger Functions can accept arguments of type File or Directory. Pass files and directories on your host by specifying their path as the value of the argument.
  • Environment variables: Pass environment variable values as argument values when invoking a function by just using the standard shell convention of using `$ENV_VAR_NAME.
  • Local network services: Dagger Functions that accept an argument of type Service can be passed local network services in the form tcp://HOST:PORT.
note

When passing values to Dagger Functions within Dagger Shell, required arguments are positional, while flags can be placed anywhere.

String arguments

Here is an example of a Dagger Function that accepts a string argument:

package main

import (
"context"
"fmt"
)

type MyModule struct{}

func (m *MyModule) GetUser(ctx context.Context, gender string) (string, error) {
return dag.Container().
From("alpine:latest").
WithExec([]string{"apk", "add", "curl"}).
WithExec([]string{"apk", "add", "jq"}).
WithExec([]string{"sh", "-c", fmt.Sprintf("curl https://randomuser.me/api/?gender=%s | jq .results[0].name", gender)}).
Stdout(ctx)
}

Here is an example call for this Dagger Function:

dagger -c 'get-user male'

The result will look something like this:

{
"title": "Mr",
"first": "Hans-Werner",
"last": "Thielen"
}

To pass host environment variables as arguments when invoking a Dagger Function, use the standard shell convention of $ENV_VAR_NAME.

Here is an example of passing a host environment variable containing a string value to a Dagger Function:

export GREETING=bonjour
dagger -c 'github.com/shykes/daggerverse/hello@v0.3.0 | hello --greeting=$GREETING'

Boolean arguments

Here is an example of a Dagger Function that accepts a Boolean argument:

package main

import (
"strings"
)

type MyModule struct{}

func (m *MyModule) Hello(shout bool) string {
message := "Hello, world"
if shout {
return strings.ToUpper(message)
}
return message
}

Here is an example call for this Dagger Function:

dagger -c 'hello true'

The result will look like this:

HELLO, WORLD
note

When passing optional boolean flags:

  • To set the argument to true: --foo=true or --foo
  • To set the argument to false: --foo=false

Integer arguments

Here is an example of a Dagger function that accepts an integer argument:

package main

type MyModule struct{}

func (m *MyModule) AddInteger(a int, b int) int {
return a + b
}

Here is an example call for this Dagger Function:

dagger -c 'add-integer 1 2'

The result will look like this:

3

Floating-point number arguments

Here is an example of a Dagger function that accepts a floating-point number as argument:

package main

type MyModule struct{}

func (m *MyModule) AddFloat(a float64, b float64) float64 {
return a + b
}

Here is an example call for this Dagger Function:

dagger -c 'add-float 1.4 2.7'

The result will look like this:

4.1

Array arguments

To pass an array argument to a Dagger Function, use a comma-separated list of values.

package main

import (
"strings"
)

type MyModule struct{}

func (m *MyModule) Hello(names []string) string {
message := "Hello"
if len(names) > 0 {
message += " " + strings.Join(names, ", ")
}

return message
}

Here is an example call for this Dagger Function:

dagger -c 'hello John,Jane'

The result will look like this:

Hello John, Jane

Directory arguments

You can also pass a directory argument from the command-line. To do so, add the corresponding flag, followed by a local filesystem path or a remote Git reference. In both cases, the CLI will convert it to an object referencing the contents of that filesystem path or Git repository location, and pass the resulting Directory object as argument to the Dagger Function.

Dagger Functions do not have access to the filesystem of the host you invoke the Dagger Function from (i.e. the host you execute a CLI command like dagger call from). Instead, host directories need to be explicitly passed as arguments to Dagger Functions.

Here's an example of a Dagger Function that accepts a Directory as argument. The Dagger Function returns a tree representation of the files and directories at that path.

package main

import (
"context"

"main/internal/dagger"
)

type MyModule struct{}

func (m *MyModule) Tree(ctx context.Context, src *dagger.Directory, depth string) (string, error) {
return dag.Container().
From("alpine:latest").
WithMountedDirectory("/mnt", src).
WithWorkdir("/mnt").
WithExec([]string{"apk", "add", "tree"}).
WithExec([]string{"tree", "-L", depth}).
Stdout(ctx)
}

Here is an example of passing a local directory to this Dagger Function as argument:

mkdir -p mydir/mysubdir
touch mydir/a mydir/b mydir/c mydir/mysubdir/y mydir/mysubdir/z
dagger -c 'tree mydir 2'

The result will look like this:

.
├── a
├── b
├── c
└── mysubdir
├── y
└── z

2 directories, 5 files

Here is an example of passing a remote repository (Dagger's open-source repository) over HTTPS as a Directory argument:

dagger <<EOF
container |
from alpine:latest |
with-directory /src https://github.com/dagger/dagger |
with-exec ls /src |
stdout
EOF

The same repository can also be accessed using SSH. Note that this requires SSH authentication to be properly configured on your Dagger host. Here is the same example, this time using SSH:

dagger <<EOF
container |
from alpine:latest |
with-directory /src ssh://git@github.com/dagger/dagger |
with-exec ls /src |
stdout
EOF

For more information about remote repository access, refer to the documentation on reference schemes and authentication methods.

note

Dagger offers two important features for working with Directory arguments:

  • Default paths: Set a default directory path to use no value is specified for the argument.
  • Filters: Control which files and directories are uploaded to a Dagger Function.

File arguments

File arguments work in the same way as directory arguments. To pass a file to a Dagger Function as an argument, add the corresponding flag, followed by a local filesystem path or a remote Git reference. In both cases, the CLI will convert it to an object referencing that filesystem path or Git repository location, and pass the resulting File object as argument to the Dagger Function.

Here's an example of a Dagger Function that accepts a File as argument, reads it, and returns its contents:

package main

import (
"context"
"dagger/my-module/internal/dagger"
)

type MyModule struct{}

func (m *MyModule) ReadFile(ctx context.Context, source *dagger.File) (string, error) {
contents, err := dag.Container().
From("alpine:latest").
WithFile("/src/myfile", source).
WithExec([]string{"cat", "/src/myfile"}).
Stdout(ctx)
if err != nil {
return "", err
}
return contents, nil
}

Here is an example of passing a local file to this Dagger Function as argument:

dagger -c 'read-file /my/file/path/README.md'

And here is an example of passing a file from a remote Git repository as argument:

dagger -c 'read-file https://github.com/dagger/dagger.git#main:README.md'

For more information about remote repository access, refer to the documentation on reference schemes and authentication methods.

note

Dagger offers two important features for working with File arguments:

  • Default paths: Set a default file path to use no value is specified for the argument.
  • Filters: Control which files are uploaded to a Dagger Function.

Container arguments

Just like directories, you can pass a container to a Dagger Function from the command-line. To do so, add the corresponding flag, followed by the address of an OCI image. The CLI will dynamically pull the image, and pass the resulting Container object as argument to the Dagger Function.

Here is an example of a Dagger Function that accepts a container image reference as an argument. The Dagger Function returns operating system information for the container.

package main

import (
"context"

"main/internal/dagger"
)

type MyModule struct{}

func (m *MyModule) OsInfo(ctx context.Context, ctr *dagger.Container) (string, error) {
return ctr.
WithExec([]string{"uname", "-a"}).
Stdout(ctx)
}

Here is an example of passing a container image reference to this Dagger Function as an argument.

dagger -c 'os-info ubuntu:latest'

The result will look like this:

Linux dagger 6.1.0-22-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.94-1 (2024-06-21) x86_64 x86_64 x86_64 GNU/Linux

Here is another example of passing a container image reference to a Dagger Function as an argument. The Dagger Function scans the container using Trivy and reports any vulnerabilities found.

dagger -c 'github.com/jpadams/daggerverse/trivy@v0.3.0 | scan-container index.docker.io/alpine:latest'

Secret arguments

Dagger allows you to utilize confidential information, such as passwords, API keys, SSH keys and so on, in your Dagger modules and Dagger Functions, without exposing those secrets in plaintext logs, writing them into the filesystem of containers you're building, or inserting them into the cache.

Secrets can be passed to Dagger Functions as arguments using the Secret core type. Here is an example of a Dagger Function which accepts a GitHub personal access token as a secret, and uses the token to authorize a request to the GitHub API:

package main

import (
"context"

"dagger/my-module/internal/dagger"
)

type MyModule struct{}

// Query the GitHub API
func (m *MyModule) GithubApi(
ctx context.Context,
// GitHub API token
token *dagger.Secret,
) (string, error) {
return dag.Container().
From("alpine:3.17").
WithSecretVariable("GITHUB_API_TOKEN", token).
WithExec([]string{"apk", "add", "curl"}).
WithExec([]string{"sh", "-c", `curl "https://api.github.com/repos/dagger/dagger/issues" --header "Accept: application/vnd.github+json" --header "Authorization: Bearer $GITHUB_API_TOKEN"`}).
Stdout(ctx)
}

The result will be a JSON-formatted list of issues from Dagger's repository.

When invoking the Dagger Function using the Dagger CLI, secrets can be sourced from multiple providers. Dagger can read secrets from the host environment, the host filesystem, and the result of host command execution, as well as from external secret managers 1Password and Vault.

Host secret providers

Here is an example call for this Dagger Function, with the secret sourced from a host environment variable named GITHUB_API_TOKEN via the env provider:

dagger -c 'github-api env://GITHUB_API_TOKEN'

Secrets can also be passed from a host file using the file provider:

dagger -c 'github-api file://./github.txt'

...or as the result of executing a command on the host using the cmd provider:

dagger -c 'github-api cmd://"gh auth token"'

External secret providers

Secrets can also be sourced from external secret managers. Currently, Dagger supports 1Password and Vault.

1Password requires creating a service account and then setting the OP_SERVICE_ACCOUNT_TOKEN environment variable. Alternatively, if no OP_SERVICE_ACCOUNT_TOKEN is provided, the integration will attempt to execute the (official) op CLI if installed in the system.

1Password secret references, in the format op://VAULT-NAME/ITEM-NAME/[SECTION-NAME/]FIELD-NAME are supported. Here is an example:

export OP_SERVICE_ACCOUNT_TOKEN="mytoken"
dagger -c 'github-api op://infra/github/credential'

Vault can be authenticated with either token or AppRole methods. The Vault host can be specified by setting the environment variable VAULT_ADDR. For token authentication, set the environment variable VAULT_TOKEN. For AppRole authentication, set the environment variables VAULT_APPROLE_ROLE_ID and VAULT_APPROLE_SECRET_ID. Additional client configuration can be specified by the default environment variables accepted by Vault.

Vault KvV2 secrets are accessed with the scheme vault://PATH/TO/SECRET.ITEM. If your KvV2 is not mounted at /secret, specify the mount location with the environment variable VAULT_PATH_PREFIX. Here is an example:

export VAULT_ADDR='https://example.com:8200'
export VAULT_TOKEN=abcd_1234
dagger -c 'github-api vault://infra/github.credential'

Service arguments

Host network services or sockets can be passed to Dagger Functions as arguments. To do so, add the corresponding flag, followed by a service or socket reference.

TCP and UDP services

To pass host TCP or UDP network services as arguments when invoking a Dagger Function, specify them in the form tcp://HOST:PORT or udp://HOST:PORT.

Assume that you have a PostgresQL database running locally on port 5432, as with:

docker run --rm -d -e POSTGRES_PASSWORD=postgres -p 5432:5432 postgres

Here is an example of passing this host service as argument to a PostgreSQL client Dagger Function, which drops you to a prompt from where you can execute SQL queries:

dagger <<EOF
github.com/kpenfound/dagger-modules/postgres@v0.1.0 |
client tcp://localhost:5432 postgres postgres postgres
EOF

Unix sockets

Similar to host TCP/UDP services, Dagger Functions can also be granted access to host Unix sockets when the client is running on Linux or MacOS.

To pass host Unix sockets as arguments when invoking a Dagger Function, specify them by their path on the host.

For example, assuming you have Docker on your host with the Docker daemon listening on a Unix socket at /var/run/docker.sock, you can pass this socket to a Docker client Dagger Function as follows:

dagger -c 'github.com/sipsma/daggerverse/docker-client@v0.0.1 /var/run/docker.sock | version'

Optional arguments

Function arguments can be marked as optional. In this case, the Dagger CLI will not display an error if the argument is omitted in the function call.

Here's an example of a Dagger Function with an optional argument:

package main

import (
"context"
"fmt"
)

type MyModule struct{}

func (m *MyModule) Hello(
ctx context.Context,
// +optional
name string,
) (string, error) {
if name != "" {
return fmt.Sprintf("Hello, %s", name), nil
} else {
return "Hello, world", nil
}
}

Here is an example call for this Dagger Function, with the optional argument:

dagger -c 'hello --name=John'

The result will look like this:

Hello, John

Here is an example call for this Dagger Function, without the optional argument:

dagger -c hello

The result will look like this:

Hello, world

Default values

Function arguments can define a default value if no value is supplied for them.

Here's an example of a Dagger Function with a default value for a string argument:

package main

import (
"context"
"fmt"
)

type MyModule struct{}

func (m *MyModule) Hello(
ctx context.Context,
// +default="world"
name string,
) (string, error) {
return fmt.Sprintf("Hello, %s", name), nil
}

Here is an example call for this Dagger Function, without the required argument:

dagger -c hello

The result will look like this:

Hello, world

Passing null to an optional argument signals that no default value should be used.

note

Dagger supports default paths for Directory or File arguments. Dagger will automatically use this default path when no value is specified for the corresponding argument.

Reference schemes for remote repositories

Dagger supports the use of HTTP and SSH protocols for accessing files and directories in remote repositories, compatible with all major Git hosting platforms such as GitHub, GitLab, BitBucket, Azure DevOps, Codeberg, and Sourcehut. Dagger supports authentication via both HTTPS (using Git credential managers) and SSH (using a unified authentication approach).

Dagger supports the following reference schemes for file and directory arguments:

ProtocolSchemeAuthenticationExample
HTTP(S)Git HTTPGit credential managerhttps://github.com/username/repo.git[#version[:subpath]]
SSHExplicitSSH keysssh://git@github.com/username/repo.git[#version[:subpath]]
SSHSCP-likeSSH keysgit@github.com:username/repo.git[#version[:subpath]]
note

The reference scheme for directory arguments is currently under discussion here and here and may change in future.

Dagger provides additional flexibility in referencing file and directory arguments through the following options:

  • Version specification: Add #version to target a particular version of the repository. This can be a tag, branch name, or full commit hash. If omitted, the default branch is used.
  • Monorepo support: Append :subpath after the version specification to access a specific subdirectory within the repository. Note that specifying a version is mandatory when including a subpath.
important

When referencing a specific subdirectory (subpath) within a repository, you must always include a version specification. The format is always #version:subpath.