Interactive Terminal
Dagger provides an interactive terminal that can help greatly when trying to debug a pipeline failure.
To use this, set one or more explicit breakpoints in your Dagger pipeline with the Container.terminal()
method. Dagger then starts an interactive terminal session at each breakpoint. This lets you inspect a Directory
or a Container
at any point in your pipeline run, with all the necessary context available to you.
Here is a simple example, which opens an interactive terminal in an alpine
container:
dagger core container from --address=alpine terminal
Here is an example of a Dagger Function which opens an interactive terminal at two different points in the Dagger pipeline to inspect the built container:
- Go
- Python
- TypeScript
package main
import (
"dagger/my-module/internal/dagger"
)
type MyModule struct{}
func (m *MyModule) Container() *dagger.Container {
return dag.Container().
From("alpine:latest").
Terminal().
WithExec([]string{"sh", "-c", "echo hello world > /foo && cat /foo"}).
Terminal()
}
import dagger
from dagger import dag, function, object_type
@object_type
class MyModule:
@function
def container(self) -> dagger.Container:
return (
dag.container()
.from_("alpine:latest")
.terminal()
.with_exec(["sh", "-c", "echo hello world > /foo && cat /foo"])
.terminal()
)
import { dag, Container, object, func } from "@dagger.io/dagger"
@object()
class MyModule {
@func()
container(): Container {
return dag
.container()
.from("alpine:latest")
.terminal()
.withExec(["sh", "-c", "echo hello world > /foo && cat /foo"])
.terminal()
}
}
The Container.terminal()
method can be chained. It returns a Container
, so it can be injected at any point in a pipeline (in this example, between Container.from()
and Container.withExec()
methods).
Multiple terminals are supported in the same Dagger Function; they will open in sequence.
It's also possible to inspect a directory using the Container.terminal()
method. Here is an example of a Dagger Function which opens an interactive terminal on a directory:
- Go
- Python
- TypeScript
package main
import (
"context"
)
type MyModule struct{}
func (m *MyModule) SimpleDirectory(ctx context.Context) (string, error) {
return dag.
Git("https://github.com/dagger/dagger.git").
Head().
Tree().
Terminal().
File("README.md").
Contents(ctx)
}
from dagger import dag, function, object_type
@object_type
class MyModule:
@function
async def simple_directory(self) -> str:
return await (
dag.git("https://github.com/dagger/dagger.git")
.head()
.tree()
.terminal()
.file("README.md")
.contents()
)
import { dag, Container, object, func } from "@dagger.io/dagger"
@object()
class MyModule {
@func()
async simpleDirectory(): Promise<string> {
return await dag
.git("https://github.com/dagger/dagger.git")
.head()
.tree()
.terminal()
.file("README.md")
.contents()
}
}
Under the hood, this creates a new container (defaults to alpine
) and starts a shell, mounting the directory inside. This container can be customized using additional options. Here is a more complex example, which produces the same result as the previous one but this time using an ubuntu
container image and bash
shell instead of the default alpine
container image and sh
shell:
- Go
- Python
- TypeScript
package main
import (
"context"
"dagger/my-module/internal/dagger"
)
type MyModule struct{}
func (m *MyModule) AdvancedDirectory(ctx context.Context) (string, error) {
return dag.
Git("https://github.com/dagger/dagger.git").
Head().
Tree().
Terminal(dagger.DirectoryTerminalOpts{
Container: dag.Container().From("ubuntu"),
Cmd: []string{"/bin/bash"},
}).
File("README.md").
Contents(ctx)
}
from dagger import dag, function, object_type
@object_type
class MyModule:
@function
async def advanced_directory(self) -> str:
return await (
dag.git("https://github.com/dagger/dagger.git")
.head()
.tree()
.terminal(
container=dag.container().from_("ubuntu"),
cmd=["/bin/bash"],
)
.file("README.md")
.contents()
)
import { dag, Container, object, func } from "@dagger.io/dagger"
@object()
class MyModule {
@func()
async advancedDirectory(): Promise<string> {
return await dag
.git("https://github.com/dagger/dagger.git")
.head()
.tree()
.terminal({
container: dag.container().from("ubuntu"),
cmd: ["/bin/bash"],
})
.file("README.md")
.contents()
}
}