nemo_gym.sandbox.providers.docker.provider

View as Markdown

Docker sandbox provider: one long-lived container per sandbox, driven via the docker CLI.

Module Contents

Classes

NameDescription
DockerCreateConfig-
DockerCreateErrorRaised when Docker cannot create a sandbox.
DockerCreateVerificationErrorRaised when a new container fails its readiness probe.
DockerExecConfig-
DockerProbeConfig-
DockerProviderSandbox provider backed by the local Docker CLI / daemon.
_DockerContainer-

Functions

Data

CONTAINER_NAME_PREFIX

DEFAULT_KEEPALIVE_CMD

DEFAULT_KEEPALIVE_SHELL

DOCKER_MISSING_CONTAINER_MARKERS

DOCKER_RUNTIME_ERROR_MARKERS

LOGGER

READY_PROBE_COMMAND

READY_PROBE_EXPECTED

SANDBOX_LABEL

SANDBOX_RUNTIME_RETURN_CODE

API

class nemo_gym.sandbox.providers.docker.provider.DockerCreateConfig(
keepalive_shell: str = DEFAULT_KEEPALIVE_SHELL,
keepalive_cmd: str = DEFAULT_KEEPALIVE_CMD,
start_timeout_s: float | None = 600,
use_init: bool = True,
network: str | None = None,
read_only: bool = False,
cap_drop: list[str] = list(),
security_opt: list[str] = list(),
pids_limit: int | None = None,
extra_run_args: list[str] = list(),
apply_resource_limits: bool = True
)
Dataclass
apply_resource_limits
bool = True
cap_drop
list[str] = field(default_factory=list)
extra_run_args
list[str] = field(default_factory=list)
keepalive_cmd
str = DEFAULT_KEEPALIVE_CMD
keepalive_shell
str = DEFAULT_KEEPALIVE_SHELL
network
str | None = None
pids_limit
int | None = None
read_only
bool = False
security_opt
list[str] = field(default_factory=list)
start_timeout_s
float | None = 600
use_init
bool = True
nemo_gym.sandbox.providers.docker.provider.DockerCreateConfig.__post_init__() -> None
class nemo_gym.sandbox.providers.docker.provider.DockerCreateError()

Bases: SandboxCreateError

Raised when Docker cannot create a sandbox.

class nemo_gym.sandbox.providers.docker.provider.DockerCreateVerificationError()

Bases: SandboxCreateVerificationError

Raised when a new container fails its readiness probe.

class nemo_gym.sandbox.providers.docker.provider.DockerExecConfig(
default_timeout_s: float | None = 180,
extra_exec_args: list[str] = list(),
concurrency: int = 32,
exec_shell: str | None = None
)
Dataclass
concurrency
int = 32
default_timeout_s
float | None = 180
exec_shell
str | None = None
extra_exec_args
list[str] = field(default_factory=list)
nemo_gym.sandbox.providers.docker.provider.DockerExecConfig.__post_init__() -> None
class nemo_gym.sandbox.providers.docker.provider.DockerProbeConfig(
command: str | None = READY_PROBE_COMMAND,
expected_stdout: str | None = READY_PROBE_EXPECTED,
timeout_s: int = 30,
deadline_s: float | None = None,
stable_count: int = 1,
stable_delay_s: float = 0.0
)
Dataclass
command
str | None = READY_PROBE_COMMAND
deadline_s
float | None = None
expected_stdout
str | None = READY_PROBE_EXPECTED
stable_count
int = 1
stable_delay_s
float = 0.0
timeout_s
int = 30
nemo_gym.sandbox.providers.docker.provider.DockerProbeConfig.__post_init__() -> None
class nemo_gym.sandbox.providers.docker.provider.DockerProvider(
exec: nemo_gym.sandbox.providers.docker.provider.DockerExecConfig | collections.abc.Mapping[str, typing.Any] | None = None,
create: nemo_gym.sandbox.providers.docker.provider.DockerCreateConfig | collections.abc.Mapping[str, typing.Any] | None = None,
probe: nemo_gym.sandbox.providers.docker.provider.DockerProbeConfig | collections.abc.Mapping[str, typing.Any] | None = None
)

Sandbox provider backed by the local Docker CLI / daemon.

_binary
= _require_docker()
_create_config
= _coerce_config(create, DockerCreateConfig)
_exec_config
= _coerce_config(exec, DockerExecConfig)
_probe
= _coerce_config(probe, DockerProbeConfig)
_semaphore
= asyncio.Semaphore(self._exec_config.concurrency)
name
= 'docker'
nemo_gym.sandbox.providers.docker.provider.DockerProvider._cleanup_failed_create_handle(
handle: nemo_gym.sandbox.providers.base.SandboxHandle
) -> None
async
nemo_gym.sandbox.providers.docker.provider.DockerProvider._force_remove(
name: str
) -> None
async
nemo_gym.sandbox.providers.docker.provider.DockerProvider._resolve_shell(
name: str
) -> str
async

Configured exec shell, else bash when the image has it (for conda source), else sh.

nemo_gym.sandbox.providers.docker.provider.DockerProvider._run(
argv: list[str],
timeout_s: float | None,
stdin: bytes | None = None
) -> tuple[int, str, str]
async

Run a docker CLI command as (return_code, stdout, stderr); SIGKILL the group on timeout.

nemo_gym.sandbox.providers.docker.provider.DockerProvider._verify_created_handle(
handle: nemo_gym.sandbox.providers.base.SandboxHandle
) -> None
async

Poll the readiness probe until it passes stable_count times or the deadline elapses.

nemo_gym.sandbox.providers.docker.provider.DockerProvider.aclose() -> None
async
nemo_gym.sandbox.providers.docker.provider.DockerProvider.close(
handle: nemo_gym.sandbox.providers.base.SandboxHandle
) -> None
async

Force-remove the container (already-gone counts as success).

nemo_gym.sandbox.providers.docker.provider.DockerProvider.create(
spec: nemo_gym.sandbox.providers.base.SandboxSpec
) -> nemo_gym.sandbox.providers.base.SandboxHandle
async

Start a detached keep-alive container (image ENTRYPOINT overridden) and probe readiness.

spec.ttl_s bounds the lifetime (the keep-alive sleeps for it and --rm self-removes on exit). spec.provider_options may carry volumes (-> -v) and run_args (extra run flags). A half-created container is force-removed on any failure.

nemo_gym.sandbox.providers.docker.provider.DockerProvider.download_file(
handle: nemo_gym.sandbox.providers.base.SandboxHandle,
source_path: str,
target_path: pathlib.Path
) -> None
async

Download one container file to the host.

nemo_gym.sandbox.providers.docker.provider.DockerProvider.exec(
handle: nemo_gym.sandbox.providers.base.SandboxHandle,
command: str,
cwd: str | None = None,
env: dict[str, str] | None = None,
timeout_s: int | float | None = None,
user: str | int | None = None,
stdin: bytes | None = None
) -> nemo_gym.sandbox.providers.base.SandboxExecResult
async

Run <shell> -c <command> via docker exec; never raises for command failure.

user maps to --user (root/0 -> 0). A timeout kills the local docker client only; the in-container process is reaped when the sandbox is closed.

nemo_gym.sandbox.providers.docker.provider.DockerProvider.status(
handle: nemo_gym.sandbox.providers.base.SandboxHandle
) -> nemo_gym.sandbox.providers.base.SandboxStatus
async

Container status via docker inspect (missing -> STOPPED; error/timeout -> UNKNOWN).

nemo_gym.sandbox.providers.docker.provider.DockerProvider.upload_file(
handle: nemo_gym.sandbox.providers.base.SandboxHandle,
source_path: pathlib.Path,
target_path: str
) -> None
async

Upload one host file (creates the parent dir; the file lands owned by root).

class nemo_gym.sandbox.providers.docker.provider._DockerContainer(
name: str,
image: str,
shell: str = 'sh',
env: dict[str, str] = dict()
)
Dataclass
env
dict[str, str] = field(default_factory=dict)
image
str
name
str
shell
str = 'sh'
nemo_gym.sandbox.providers.docker.provider._coerce_config(
value: typing.Any,
config_cls: type[typing.Any]
) -> typing.Any
nemo_gym.sandbox.providers.docker.provider._coerce_str_list(
value: typing.Any,
what: str
) -> list[str]
nemo_gym.sandbox.providers.docker.provider._is_missing_container(
stderr: str
) -> bool
nemo_gym.sandbox.providers.docker.provider._is_runtime_failure(
stderr: str
) -> bool
nemo_gym.sandbox.providers.docker.provider._normalize_image(
image: str
) -> str
nemo_gym.sandbox.providers.docker.provider._redact_argv(
argv: list[str]
) -> list[str]

argv copy with --env KEY=VALUE values masked, so timeouts/logs don’t leak secrets.

nemo_gym.sandbox.providers.docker.provider._require_docker() -> str
nemo_gym.sandbox.providers.docker.provider._resource_limit_flags(
resources: nemo_gym.sandbox.providers.base.SandboxResources
) -> list[str]
nemo_gym.sandbox.providers.docker.provider._resource_passthrough_flags(
resources: nemo_gym.sandbox.providers.base.SandboxResources
) -> list[str]
nemo_gym.sandbox.providers.docker.provider._to_sandbox_status(
state: str | None
) -> nemo_gym.sandbox.providers.base.SandboxStatus
nemo_gym.sandbox.providers.docker.provider.CONTAINER_NAME_PREFIX = 'nemo-gym-'
nemo_gym.sandbox.providers.docker.provider.DEFAULT_KEEPALIVE_CMD = 'while :; do sleep 2147483647; done'
nemo_gym.sandbox.providers.docker.provider.DEFAULT_KEEPALIVE_SHELL = '/bin/sh'
nemo_gym.sandbox.providers.docker.provider.DOCKER_MISSING_CONTAINER_MARKERS = ('no such container', 'no such object')
nemo_gym.sandbox.providers.docker.provider.DOCKER_RUNTIME_ERROR_MARKERS = ('no such container', 'is not running', 'is not paused', 'cannot connect to the ...
nemo_gym.sandbox.providers.docker.provider.LOGGER = logging.getLogger(__name__)
nemo_gym.sandbox.providers.docker.provider.READY_PROBE_COMMAND = 'printf docker-sandbox-ready'
nemo_gym.sandbox.providers.docker.provider.READY_PROBE_EXPECTED = 'docker-sandbox-ready'
nemo_gym.sandbox.providers.docker.provider.SANDBOX_LABEL = 'nemo-gym.sandbox'
nemo_gym.sandbox.providers.docker.provider.SANDBOX_RUNTIME_RETURN_CODE = 125