Class: RubyLLM::Toolbox::Sandbox::Docker

Inherits:
Base
  • Object
show all
Defined in:
lib/ruby_llm/toolbox/sandbox/docker.rb

Overview

Runs a command inside a hardened, ephemeral Docker container. The host docker client runs with the normal environment (so DOCKER_HOST etc. are honored); all isolation is applied to the container:

--rm                      ephemeral, removed on exit
--network none            no network by default
--read-only + tmpfs /tmp  immutable root, scratch space only in tmpfs
--cap-drop ALL            no Linux capabilities
--security-opt no-new-privileges
--user <uid:gid>          non-root
--memory/--cpus/--pids-limit   resource caps

The program is array-form (no shell). Source is fed on stdin, so nothing from the host filesystem is mounted into the container. Unlike the host-process backends, the container only sees its image — not the host.

Constant Summary collapse

Unavailable =

Kept for backwards compatibility; the canonical error is Sandbox::Unavailable.

Sandbox::Unavailable

Instance Attribute Summary

Attributes inherited from Base

#config

Instance Method Summary collapse

Methods inherited from Base

#initialize, #name

Constructor Details

This class inherits a constructor from RubyLLM::Toolbox::Sandbox::Base

Instance Method Details

#available?Boolean

Returns:

  • (Boolean)


29
30
31
32
33
# File 'lib/ruby_llm/toolbox/sandbox/docker.rb', line 29

def available?
  system("docker", "version", out: File::NULL, err: File::NULL)
rescue StandardError
  false
end

#command(command_argv, image: nil) ⇒ Object Also known as: docker_argv

Exposed so the exact isolation flags can be asserted in tests.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/ruby_llm/toolbox/sandbox/docker.rb', line 47

def command(command_argv, image: nil)
  [
    "docker", "run", "--rm", "-i",
    "--network", config.sandbox_network,
    "--memory", config.sandbox_memory,
    "--cpus", config.sandbox_cpus.to_s,
    "--pids-limit", config.sandbox_pids.to_s,
    "--read-only",
    "--tmpfs", "/tmp:rw,size=64m",
    "--cap-drop", "ALL",
    "--security-opt", "no-new-privileges",
    "--user", config.sandbox_user,
    image || config.docker_image,
    *command_argv
  ]
end

#run(command_argv, stdin: nil, image: nil) ⇒ Object

Raises:



35
36
37
38
39
40
41
42
43
44
# File 'lib/ruby_llm/toolbox/sandbox/docker.rb', line 35

def run(command_argv, stdin: nil, image: nil)
  raise Unavailable, "docker was not found or is not running on the host" unless available?

  ProcessRunner.capture(
    command(command_argv, image: image),
    stdin: stdin,
    timeout: config.command_timeout,
    unsetenv_others: false # the docker *client* needs the host env
  )
end