Docker exec lets you run a new process inside an already-running container without interfering with its primary process. Bollard models this as a two-step async flow: first create an exec instance withDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/fussybeaver/bollard/llms.txt
Use this file to discover all available pages before exploring further.
create_exec, then start it with start_exec. The result is either an attached stream of output or a detached fire-and-forget.
Creating an Exec Instance
create_exec accepts a container name and a config that implements Into<ExecConfig>. The most common way to build the config is with bollard::models::ExecConfig directly.
ExecConfig:
| Field | Type | Purpose |
|---|---|---|
cmd | Option<Vec<String>> | Command and arguments to run |
attach_stdout | Option<bool> | Capture stdout |
attach_stderr | Option<bool> | Capture stderr |
attach_stdin | Option<bool> | Connect stdin (for interactive use) |
tty | Option<bool> | Allocate a pseudo-TTY |
env | Option<Vec<String>> | Extra environment variables (KEY=value) |
working_dir | Option<String> | Working directory inside the container |
privileged | Option<bool> | Run with extended privileges |
user | Option<String> | User to run as (user, user:group, uid, uid:gid) |
You can also use
bollard::exec::CreateExecOptions<T> which is generic over
string types. It converts to ExecConfig via From. The bollard::models::ExecConfig
approach shown here is more ergonomic for most use cases.Starting Exec
start_exec takes the exec ID and an optional StartExecOptions. It returns StartExecResults.
StartExecOptions has two notable fields:
detach: bool— whentrue, the process starts in the background andStartExecResults::Detachedis returned immediately.tty: bool— allocate a TTY for the exec session.
Consuming Attached Output
When exec is started in attached mode,start_exec returns StartExecResults::Attached { output, input }. The output field is a Stream<Item = Result<LogOutput, Error>>.
LogOutput implements Display, so print!("{msg}") prints the raw text.
Use msg.into_bytes() to get the raw Bytes, or match on the enum variants
(LogOutput::StdOut, LogOutput::StdErr, etc.) to handle stdout and stderr
separately.Interactive Exec
For interactive commands, setattach_stdin: Some(true) and tty: Some(true) when creating the exec, then write bytes to the input writer returned by start_exec.
Inspecting Exec
After the exec finishes, callinspect_exec to retrieve the exit code and running status.
ExecInspectResponse fields of interest:
| Field | Description |
|---|---|
running | Option<bool> — is the process still running? |
exit_code | Option<i64> — process exit code (available after completion) |
pid | Option<i64> — host PID of the exec process |
Resizing the Exec TTY
Whentty: true, you can resize the pseudo-terminal window with resize_exec.
resize_exec only has an effect when the exec instance was created with
tty: Some(true). Calling it on a non-TTY exec is a no-op on most Docker
daemon versions.Full Working Example
The following is the complete working example from the bollard repository. It pullsalpine:3, creates a container, runs ls -l / via exec, and cleans up.
StartExecResults Variants
StartExecResults is a non-exhaustive enum with two variants:
Attached
The exec session is attached. Contains
output (a Stream<Item = Result<LogOutput, Error>>) and input (an AsyncWrite sink for stdin). Use this when you need to read stdout/stderr or write to stdin.Detached
Returned when
StartExecOptions { detach: true, .. } is passed. The process runs in the background with no stream. Use this for fire-and-forget side-effects inside the container.