pub struct ContainerManager {
inner: Arc<ContainerManagerInner>,
}Expand description
Shared container manager. Clone-on-Arc; cheap to pass around.
Fields§
§inner: Arc<ContainerManagerInner>Implementations§
Source§impl ContainerManager
impl ContainerManager
Sourcepub fn connect() -> Result<Self, ContainerError>
pub fn connect() -> Result<Self, ContainerError>
Connect to the local Docker daemon using environment/platform defaults.
Honors DOCKER_HOST env var (e.g. for rootless or remote daemons).
On Windows connects via named pipe; on macOS/Linux via Unix socket.
Sourcepub async fn check_available(&self) -> Result<(), ContainerError>
pub async fn check_available(&self) -> Result<(), ContainerError>
Ping the Docker daemon. Returns Ok(()) if available.
Sourcepub async fn ensure_running(
&self,
container_name: &str,
image: &str,
volumes: &[String],
env_vars: &[(String, String)],
) -> Result<(), ContainerError>
pub async fn ensure_running( &self, container_name: &str, image: &str, volumes: &[String], env_vars: &[(String, String)], ) -> Result<(), ContainerError>
Ensure the container for this agent is created and running.
- If it exists and is running: no-op.
- If it exists but stopped: starts it.
- If it doesn’t exist: creates and starts it.
Always queries Docker (no in-memory cache) so externally killed containers
are detected. Concurrent calls for the same container_name are
serialized via a per-container mutex. Concurrent calls for different
containers proceed in parallel.
Sourceasync fn ensure_running_locked(
&self,
container_name: &str,
image: &str,
volumes: &[String],
env_vars: &[(String, String)],
) -> Result<(), ContainerError>
async fn ensure_running_locked( &self, container_name: &str, image: &str, volumes: &[String], env_vars: &[(String, String)], ) -> Result<(), ContainerError>
Create/reuse logic for [ensure_running], run while holding the
per-container serialization lock. Split out so ensure_running can wrap
it with lock acquisition + map-entry eviction on every exit path.
Sourcepub async fn exec(
&self,
container_name: &str,
cmd: &[String],
working_dir: Option<&str>,
env_vars: &[(String, String)],
) -> Result<ExecSession, ContainerError>
pub async fn exec( &self, container_name: &str, cmd: &[String], working_dir: Option<&str>, env_vars: &[(String, String)], ) -> Result<ExecSession, ContainerError>
Launch an exec session inside a running container.
Uses -i (not -t) to avoid tty CR/LF corruption of NDJSON output.
The caller receives ExecSession whose output stream carries
multiplexed stdout/stderr for piping into the block.
Sourcepub async fn inspect_exec(
&self,
exec_id: &str,
) -> Result<Option<i64>, ContainerError>
pub async fn inspect_exec( &self, exec_id: &str, ) -> Result<Option<i64>, ContainerError>
Retrieve the exit code of a finished exec via the Docker socket.
Returns Ok(Some(code)) once the exec has exited, Ok(None) while it is
still running (no code yet) or if Docker did not report one. Call this
after the exec’s output stream has ended — unlike a child process’s
wait(), the attached output stream closing does not carry the exit
status, so the turn’s success/failure can only be known by inspecting.
Sourcepub async fn signal_exec_process(
&self,
container_name: &str,
pattern: &str,
force: bool,
) -> Result<(), ContainerError>
pub async fn signal_exec_process( &self, container_name: &str, pattern: &str, force: bool, ) -> Result<(), ContainerError>
Best-effort interruption of the turn’s process(es) inside a container.
Docker/bollard has no “kill exec” API, so we pkill the matching process
via a short detached exec. The persistent-container model runs one turn at
a time (guarded by run_lock), so a single CLI process matches pattern
(the command name, e.g. claude). -f matches the full command line
because the CLI runs under node, whose process name isn’t the CLI’s.
Requires pkill (procps) in the image. Fire-and-forget (detached); a
non-match (pkill exit 1, e.g. the turn already exited) is not an error.
Sourcepub async fn stop(
&self,
container_name: &str,
timeout_secs: i64,
) -> Result<(), ContainerError>
pub async fn stop( &self, container_name: &str, timeout_secs: i64, ) -> Result<(), ContainerError>
Gracefully stop a container. Uses SIGTERM → SIGKILL after timeout_secs.
Sourcepub async fn remove(
&self,
container_name: &str,
force: bool,
) -> Result<(), ContainerError>
pub async fn remove( &self, container_name: &str, force: bool, ) -> Result<(), ContainerError>
Remove a container (must be stopped first or use force = true).
Sourceasync fn find_container(
&self,
name: &str,
) -> Result<Option<String>, ContainerError>
async fn find_container( &self, name: &str, ) -> Result<Option<String>, ContainerError>
Returns the container status string (“running”, “exited”, …) or None if not found.
Sourceasync fn pull_image(&self, image: &str) -> Result<(), ContainerError>
async fn pull_image(&self, image: &str) -> Result<(), ContainerError>
Pull image via the Docker socket (create_image API).
Streams the pull response to completion before returning. If the image is already present locally, Docker returns an empty stream immediately — this function treats that as success (no pull needed).
Errors only on genuine pull failures (network, auth, no such image).
async fn create_and_start( &self, container_name: &str, image: &str, volumes: &[String], env_vars: &[(String, String)], ) -> Result<(), ContainerError>
Trait Implementations§
Source§impl Clone for ContainerManager
impl Clone for ContainerManager
Source§fn clone(&self) -> ContainerManager
fn clone(&self) -> ContainerManager
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for ContainerManager
impl !RefUnwindSafe for ContainerManager
impl Send for ContainerManager
impl Sync for ContainerManager
impl Unpin for ContainerManager
impl !UnwindSafe for ContainerManager
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more