//! This example will run a non-interactive command inside the container using `docker exec` use bollard::container::{Config, RemoveContainerOptions}; use bollard::Docker; use bollard::exec::{CreateExecOptions, StartExecResults}; use bollard::image::CreateImageOptions; use futures_util::stream::StreamExt; use futures_util::TryStreamExt; const IMAGE: &str = "alpine:3"; #[tokio::main] async fn main() -> Result<(), Box> { let docker = Docker::connect_with_socket_defaults().unwrap(); docker .create_image( Some(CreateImageOptions { from_image: IMAGE, ..Default::default() }), None, None, ) .try_collect::>() .await?; let alpine_config = Config { image: Some(IMAGE), tty: Some(true), ..Default::default() }; let id = docker .create_container::<&str, &str>(None, alpine_config) .await? .id; docker.start_container::(&id, None).await?; // non interactive let exec = docker .create_exec( &id, CreateExecOptions { attach_stdout: Some(true), attach_stderr: Some(true), cmd: Some(vec!["ls", "-l", "/"]), ..Default::default() }, ) .await? .id; if let StartExecResults::Attached { mut output, .. } = docker.start_exec(&exec, None).await? { while let Some(Ok(msg)) = output.next().await { print!("{}", msg); } } else { unreachable!(); } docker .remove_container( &id, Some(RemoveContainerOptions { force: true, ..Default::default() }), ) .await?; Ok(()) }