Skip to main content

Go Custom Application

note

The Dagger Go SDK requires Go 1.22 or later.

From an existing Go module, install the Dagger Go SDK using the commands below:

go get dagger.io/dagger@latest

After importing dagger.io/dagger in your Go module code, run the following command to update go.sum:

go mod tidy

This example demonstrates how to build a Go application for multiple architectures and Go versions using the Go SDK.

Clone an example project and create a new Go module in the project directory:

git clone https://go.googlesource.com/example
cd example/hello
mkdir multibuild && cd multibuild
go mod init multibuild

Create a new file in the multibuild directory named main.go and add the following code to it:

package main

import (
"context"
"fmt"

"dagger.io/dagger/dag"
)

func main() {
if err := build(context.Background()); err != nil {
fmt.Println(err)
}
}

func build(ctx context.Context) error {
fmt.Println("Building with Dagger")

// define build matrix
oses := []string{"linux", "darwin"}
arches := []string{"amd64", "arm64"}
goVersions := []string{"1.22", "1.23"}

defer dag.Close()

// get reference to the local project
src := dag.Host().Directory(".")

// create empty directory to put build outputs
outputs := dag.Directory()

for _, version := range goVersions {
// get `golang` image for specified Go version
imageTag := fmt.Sprintf("golang:%s", version)
golang := dag.Container().From(imageTag)
// mount cloned repository into `golang` image
golang = golang.WithDirectory("/src", src).WithWorkdir("/src")

for _, goos := range oses {
for _, goarch := range arches {
// create a directory for each os, arch and version
path := fmt.Sprintf("build/%s/%s/%s/", version, goos, goarch)
// set GOARCH and GOOS in the build environment
build := golang.WithEnvVariable("GOOS", goos)
build = build.WithEnvVariable("GOARCH", goarch)

// build application
build = build.WithExec([]string{"go", "build", "-o", path})

// get reference to build output directory in container
outputs = outputs.WithDirectory(path, build.Directory(path))
}
}
}
// write build artifacts to host
_, err := outputs.Export(ctx, ".")
if err != nil {
return err
}
return nil
}

This Go program imports the Dagger SDK and defines two functions. The build() function represents the workflow and creates a Dagger client, which provides an interface to the Dagger API. It also defines the build matrix, consisting of two OSs (darwin and linux) and two architectures (amd64 and arm64), and builds the Go application for each combination. The Go build process is instructed via the GOOS and GOARCH build variables, which are reset for each case.

Try the Go program by executing the command below from the project directory:

dagger run go run multibuild/main.go

The dagger run command executes the specified command in a Dagger session and displays live progress. The Go program builds the application for each OS/architecture combination and writes the build results to the host. You will see the build process run four times, once for each combination. Note that the builds are happening concurrently, because the builds do not depend on eachother.

Use the tree command to see the build artifacts on the host, as shown below:

tree build
build
├── 1.22
│ ├── darwin
│ │ ├── amd64
│ │ │ └── hello
│ │ └── arm64
│ │ └── hello
│ └── linux
│ ├── amd64
│ │ └── hello
│ └── arm64
│ └── hello
└── 1.23
├── darwin
│ ├── amd64
│ │ └── hello
│ └── arm64
│ └── hello
└── linux
├── amd64
│ └── hello
└── arm64
└── hello