ruby_llm-docker 0.0.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for running Docker containers.
6
+ #
7
+ # This tool creates and immediately starts a Docker container from a
8
+ # specified image in a single operation. It combines the functionality
9
+ # of create_container and start_container for convenience when immediate
10
+ # execution is desired.
11
+ #
12
+ # == Features
13
+ #
14
+ # - Creates and starts containers in one operation
15
+ # - Supports all container configuration options
16
+ # - Configures command execution and environment variables
17
+ # - Sets up port exposure and network configuration
18
+ # - Applies advanced host configurations and volume mounts
19
+ # - Handles container naming and labeling
20
+ #
21
+ # == Security Considerations
22
+ #
23
+ # Running containers involves significant security considerations:
24
+ # - **Immediate Execution**: Starts processes immediately upon creation
25
+ # - **Resource Consumption**: Consumes CPU, memory, and storage resources
26
+ # - **Network Exposure**: Creates active network endpoints
27
+ # - **File System Access**: Potentially accesses host directories
28
+ # - **Process Isolation**: Runs processes with configured privileges
29
+ #
30
+ # Implement strict access controls and resource monitoring.
31
+ #
32
+ # == Parameters
33
+ #
34
+ # - **image**: Docker image to use (required)
35
+ # - **name**: Custom container name (optional)
36
+ # - **cmd**: Command to execute as space-separated string (optional)
37
+ # - **env**: Environment variables as comma-separated KEY=VALUE pairs (optional)
38
+ # - **exposed_ports**: Port exposure configuration as JSON object (optional)
39
+ # - **host_config**: Advanced host configuration as JSON object (optional)
40
+ #
41
+ # == Example Usage
42
+ #
43
+ # # Simple container execution
44
+ # response = RunContainer.call(
45
+ # server_context: context,
46
+ # image: "alpine:latest",
47
+ # cmd: "echo 'Hello World'"
48
+ # )
49
+ #
50
+ # # Web server with port binding
51
+ # response = RunContainer.call(
52
+ # server_context: context,
53
+ # image: "nginx:latest",
54
+ # name: "web-server",
55
+ # exposed_ports: {"80/tcp" => {}},
56
+ # host_config: {
57
+ # "PortBindings" => {"80/tcp" => [{"HostPort" => "8080"}]}
58
+ # }
59
+ # )
60
+ #
61
+ # @see ::Docker::Container.create
62
+ # @since 0.1.0
63
+ RUN_CONTAINER_DEFINITION = ToolForge.define(:run_container) do
64
+ description 'Run a Docker container (create and start)'
65
+
66
+ param :image,
67
+ type: :string,
68
+ description: 'Image name to use (e.g., "ubuntu:22.04")'
69
+
70
+ param :name,
71
+ type: :string,
72
+ description: 'Container name (optional)',
73
+ required: false
74
+
75
+ param :cmd,
76
+ type: :string,
77
+ description: 'Command to run as space-separated string (optional, e.g., "npm start" or "python app.py")',
78
+ required: false
79
+
80
+ param :env,
81
+ type: :string,
82
+ description: 'Environment variables as comma-separated KEY=VALUE pairs (optional)',
83
+ required: false
84
+
85
+ param :exposed_ports,
86
+ type: :object,
87
+ description: 'Exposed ports as {"port/protocol": {}} (optional)',
88
+ required: false
89
+
90
+ param :host_config,
91
+ type: :object,
92
+ description: 'Host configuration including port bindings, volumes, etc. (optional)',
93
+ required: false
94
+
95
+ execute do |image:, name: nil, cmd: nil, env: nil, exposed_ports: nil, host_config: nil|
96
+ config = { 'Image' => image }
97
+ config['name'] = name if name
98
+
99
+ # Parse cmd string into array if provided
100
+ config['Cmd'] = Shellwords.split(cmd) if cmd && !cmd.strip.empty?
101
+
102
+ # Parse env string into array if provided
103
+ config['Env'] = env.split(',').map(&:strip) if env && !env.strip.empty?
104
+
105
+ config['ExposedPorts'] = exposed_ports if exposed_ports
106
+ config['HostConfig'] = host_config if host_config
107
+
108
+ container = ::Docker::Container.create(config)
109
+ container.start
110
+ container_name = container.info['Names']&.first&.delete_prefix('/')
111
+
112
+ "Container started successfully. ID: #{container.id}, Name: #{container_name}"
113
+ rescue ::Docker::Error::NotFoundError
114
+ "Image #{image} not found"
115
+ rescue ::Docker::Error::ConflictError
116
+ "Container with name #{name} already exists"
117
+ rescue StandardError => e
118
+ "Error running container: #{e.message}"
119
+ end
120
+ end
121
+
122
+ RunContainer = RUN_CONTAINER_DEFINITION.to_ruby_llm_tool
123
+ end
124
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for starting Docker containers.
6
+ #
7
+ # This tool starts a previously created Docker container that is currently
8
+ # in a "created" or "stopped" state. It transitions the container to a
9
+ # "running" state and begins executing the configured command or entrypoint.
10
+ #
11
+ # == Features
12
+ #
13
+ # - Starts containers by ID or name
14
+ # - Supports both short and full container IDs
15
+ # - Works with custom container names
16
+ # - Provides clear success/failure feedback
17
+ # - Handles container state transitions
18
+ # - Preserves all container configuration
19
+ #
20
+ # == Security Considerations
21
+ #
22
+ # Starting containers involves security implications:
23
+ # - **Process Execution**: Begins running container processes
24
+ # - **Resource Activation**: Activates CPU, memory, and I/O usage
25
+ # - **Network Activation**: Brings network interfaces online
26
+ # - **Service Exposure**: Makes configured services accessible
27
+ #
28
+ # Ensure proper monitoring and access controls are in place.
29
+ #
30
+ # == Parameters
31
+ #
32
+ # - **id**: Container ID or name (required)
33
+ # - Accepts full container IDs
34
+ # - Accepts short container IDs (first 12+ characters)
35
+ # - Accepts custom container names
36
+ #
37
+ # == Example Usage
38
+ #
39
+ # # Start by container name
40
+ # response = StartContainer.call(
41
+ # server_context: context,
42
+ # id: "web-server"
43
+ # )
44
+ #
45
+ # # Start by container ID
46
+ # response = StartContainer.call(
47
+ # server_context: context,
48
+ # id: "a1b2c3d4e5f6"
49
+ # )
50
+ #
51
+ # @see ::Docker::Container#start
52
+ # @since 0.1.0
53
+ START_CONTAINER_DEFINITION = ToolForge.define(:start_container) do
54
+ description 'Start a Docker container'
55
+
56
+ param :id,
57
+ type: :string,
58
+ description: 'Container ID or name'
59
+
60
+ execute do |id:|
61
+ container = ::Docker::Container.get(id)
62
+ container.start
63
+
64
+ "Container #{id} started successfully"
65
+ rescue ::Docker::Error::NotFoundError
66
+ "Container #{id} not found"
67
+ rescue StandardError => e
68
+ "Error starting container: #{e.message}"
69
+ end
70
+ end
71
+
72
+ StartContainer = START_CONTAINER_DEFINITION.to_ruby_llm_tool
73
+ end
74
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for stopping Docker containers.
6
+ #
7
+ # This tool gracefully stops a running Docker container by sending a
8
+ # SIGTERM signal to the main process, allowing it to shut down cleanly.
9
+ # If the container doesn't stop within the specified timeout, it will
10
+ # be forcefully killed with SIGKILL.
11
+ #
12
+ # == Features
13
+ #
14
+ # - Graceful container shutdown with SIGTERM
15
+ # - Configurable timeout for forced termination
16
+ # - Supports container identification by ID or name
17
+ # - Handles both running and already-stopped containers
18
+ # - Provides clear feedback on operation status
19
+ # - Preserves container and data integrity
20
+ #
21
+ # == Security Considerations
22
+ #
23
+ # Stopping containers affects service availability:
24
+ # - **Service Disruption**: Terminates running services and processes
25
+ # - **Data Integrity**: May interrupt ongoing operations
26
+ # - **Resource Release**: Frees CPU, memory, and network resources
27
+ # - **State Preservation**: Maintains container state for future restart
28
+ #
29
+ # Coordinate container stops with dependent services and users.
30
+ #
31
+ # == Parameters
32
+ #
33
+ # - **id**: Container ID or name (required)
34
+ # - Accepts full container IDs
35
+ # - Accepts short container IDs (first 12+ characters)
36
+ # - Accepts custom container names
37
+ # - **timeout**: Seconds to wait before killing container (optional, default: 10)
38
+ #
39
+ # == Example Usage
40
+ #
41
+ # # Stop with default timeout
42
+ # response = StopContainer.call(
43
+ # server_context: context,
44
+ # id: "web-server"
45
+ # )
46
+ #
47
+ # # Stop with custom timeout
48
+ # response = StopContainer.call(
49
+ # server_context: context,
50
+ # id: "database",
51
+ # timeout: 30
52
+ # )
53
+ #
54
+ # @see ::Docker::Container#stop
55
+ # @since 0.1.0
56
+ STOP_CONTAINER_DEFINITION = ToolForge.define(:stop_container) do
57
+ description 'Stop a Docker container'
58
+
59
+ param :id,
60
+ type: :string,
61
+ description: 'Container ID or name'
62
+
63
+ param :timeout,
64
+ type: :integer,
65
+ description: 'Seconds to wait before killing the container (default: 10)',
66
+ required: false,
67
+ default: 10
68
+
69
+ execute do |id:, timeout: 10|
70
+ container = ::Docker::Container.get(id)
71
+ container.stop('timeout' => timeout)
72
+
73
+ "Container #{id} stopped successfully"
74
+ rescue ::Docker::Error::NotFoundError
75
+ "Container #{id} not found"
76
+ rescue StandardError => e
77
+ "Error stopping container: #{e.message}"
78
+ end
79
+ end
80
+
81
+ StopContainer = STOP_CONTAINER_DEFINITION.to_ruby_llm_tool
82
+ end
83
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for tagging Docker images.
6
+ #
7
+ # This tool provides the ability to assign repository names and tags
8
+ # to Docker images. Tagging is essential for image organization,
9
+ # versioning, and distribution through Docker registries.
10
+ #
11
+ # == Features
12
+ #
13
+ # - Tag existing images with custom repository names
14
+ # - Support for version and environment tags
15
+ # - Force tagging to overwrite existing tags
16
+ # - Registry-compatible naming conventions
17
+ # - Automatic tag defaulting to "latest"
18
+ # - Comprehensive error handling and validation
19
+ #
20
+ # == Security Considerations
21
+ #
22
+ # Image tagging involves several security considerations:
23
+ # - **Registry Authentication**: Tags may trigger registry operations
24
+ # - **Namespace Conflicts**: Overwriting tags can affect other deployments
25
+ # - **Image Identity**: Improper tagging can lead to deployment confusion
26
+ # - **Version Management**: Incorrect tags can compromise CI/CD pipelines
27
+ # - **Registry Pollution**: Excessive tagging can clutter registries
28
+ #
29
+ # **Security Recommendations**:
30
+ # - Use consistent naming conventions
31
+ # - Implement tag governance policies
32
+ # - Verify image identity before tagging
33
+ # - Avoid overwriting production tags
34
+ # - Use semantic versioning for releases
35
+ # - Monitor tag usage and lifecycle
36
+ #
37
+ # == Parameters
38
+ #
39
+ # - **id**: Image ID or current name:tag to tag (required)
40
+ # - **repo**: Repository name (required, e.g., "username/imagename" or "registry/username/imagename")
41
+ # - **tag**: Tag for the image (optional, default: "latest")
42
+ # - **force**: Force tag even if it already exists (optional, default: true)
43
+ #
44
+ # == Example Usage
45
+ #
46
+ # # Tag image with version
47
+ # response = TagImage.call(
48
+ # server_context: context,
49
+ # id: "myapp:dev",
50
+ # repo: "myregistry/myapp",
51
+ # tag: "v1.2.3"
52
+ # )
53
+ #
54
+ # # Tag for production deployment
55
+ # response = TagImage.call(
56
+ # server_context: context,
57
+ # id: "abc123def456",
58
+ # repo: "production/webapp",
59
+ # tag: "stable",
60
+ # force: false
61
+ # )
62
+ #
63
+ # # Tag with registry prefix
64
+ # response = TagImage.call(
65
+ # server_context: context,
66
+ # id: "local-build:latest",
67
+ # repo: "registry.company.com/team/service",
68
+ # tag: "release-candidate"
69
+ # )
70
+ #
71
+ # @see ::Docker::Image#tag
72
+ # @since 0.1.0
73
+ TAG_IMAGE_DEFINITION = ToolForge.define(:tag_image) do
74
+ description 'Tag a Docker image'
75
+
76
+ param :id,
77
+ type: :string,
78
+ description: 'Image ID or current name:tag to tag'
79
+
80
+ param :repo,
81
+ type: :string,
82
+ description: 'Repository name (e.g., "username/imagename" or "registry/username/imagename")'
83
+
84
+ param :tag,
85
+ type: :string,
86
+ description: 'Tag for the image (default: "latest")',
87
+ required: false,
88
+ default: 'latest'
89
+
90
+ param :force,
91
+ type: :boolean,
92
+ description: 'Force tag even if it already exists (default: true)',
93
+ required: false,
94
+ default: true
95
+
96
+ execute do |id:, repo:, tag: 'latest', force: true|
97
+ image = ::Docker::Image.get(id)
98
+
99
+ image.tag('repo' => repo, 'tag' => tag, 'force' => force)
100
+
101
+ "Image tagged successfully as #{repo}:#{tag}"
102
+ rescue ::Docker::Error::NotFoundError
103
+ "Image #{id} not found"
104
+ rescue StandardError => e
105
+ "Error tagging image: #{e.message}"
106
+ end
107
+ end
108
+
109
+ TagImage = TAG_IMAGE_DEFINITION.to_ruby_llm_tool
110
+ end
111
+ end
@@ -1,7 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RubyLlm
3
+ module RubyLLM
4
4
  module Docker
5
- VERSION = "0.0.1"
5
+ # Current version of the RubyLLM::Docker gem.
6
+ #
7
+ # This constant follows semantic versioning (SemVer) principles:
8
+ # - MAJOR version for incompatible API changes
9
+ # - MINOR version for backwards-compatible functionality additions
10
+ # - PATCH version for backwards-compatible bug fixes
11
+ #
12
+ # @see https://semver.org/
13
+ # @since 0.1.0
14
+ VERSION = '0.3.0'
6
15
  end
7
16
  end
@@ -1,10 +1,73 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "docker/version"
3
+ require 'ruby_llm'
4
+ require 'docker'
5
+ require 'shellwords'
6
+ require 'tool_forge'
7
+ require 'zeitwerk'
4
8
 
5
- module RubyLlm
9
+ loader = Zeitwerk::Loader.for_gem_extension(RubyLLM)
10
+ loader.setup
11
+
12
+ require_relative 'docker/version'
13
+
14
+ module RubyLLM
15
+ # Docker tools module providing comprehensive Docker management capabilities for RubyLLM.
16
+ #
17
+ # This module contains 22 Docker management tools organized into four categories:
18
+ # - Container Management (10 tools)
19
+ # - Image Management (6 tools)
20
+ # - Network Management (3 tools)
21
+ # - Volume Management (3 tools)
22
+ #
23
+ # @example Basic usage
24
+ # chat = RubyLLM::Chat.new(api_key: 'your-key', model: 'gpt-4')
25
+ # RubyLLM::Docker.add_all_tools_to_chat(chat)
26
+ # response = chat.ask("How many containers are running?")
6
27
  module Docker
7
28
  class Error < StandardError; end
8
- # Your code goes here...
29
+
30
+ # Helper method to get all Docker tool classes
31
+ def self.all_tools
32
+ [
33
+ # Container Management
34
+ ListContainers,
35
+ CreateContainer,
36
+ RunContainer,
37
+ StartContainer,
38
+ StopContainer,
39
+ RemoveContainer,
40
+ RecreateContainer,
41
+ ExecContainer,
42
+ CopyToContainer,
43
+ FetchContainerLogs,
44
+
45
+ # Image Management
46
+ ListImages,
47
+ PullImage,
48
+ BuildImage,
49
+ TagImage,
50
+ PushImage,
51
+ RemoveImage,
52
+
53
+ # Network Management
54
+ ListNetworks,
55
+ CreateNetwork,
56
+ RemoveNetwork,
57
+
58
+ # Volume Management
59
+ ListVolumes,
60
+ CreateVolume,
61
+ RemoveVolume
62
+ ]
63
+ end
64
+
65
+ # Helper method to add all Docker tools to a RubyLLM chat instance
66
+ def self.add_all_tools_to_chat(chat)
67
+ all_tools.each do |tool_class|
68
+ chat.with_tool(tool_class)
69
+ end
70
+ chat
71
+ end
9
72
  end
10
73
  end
@@ -1,4 +1,4 @@
1
- module RubyLlm
1
+ module RubyLLM
2
2
  module Docker
3
3
  VERSION: String
4
4
  # See the writing guide of rbs: https://github.com/ruby/rbs#guides
metadata CHANGED
@@ -1,16 +1,88 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_llm-docker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron F Stanton
8
8
  bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
- dependencies: []
12
- description: This gem provides a simple interface for managing Docker containers from
13
- Ruby via RubyLLM.
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: base64
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: docker-api
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: ruby_llm
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: tool_forge
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: zeitwerk
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ description: A comprehensive Ruby gem that provides Docker management capabilities
83
+ through RubyLLM tools. Enables AI assistants to interact with Docker containers,
84
+ images, networks, and volumes using natural language. Ported from DockerMCP to work
85
+ directly with RubyLLM without requiring an external MCP server.
14
86
  email:
15
87
  - afstanton@gmail.com
16
88
  executables: []
@@ -20,7 +92,32 @@ files:
20
92
  - LICENSE.txt
21
93
  - README.md
22
94
  - Rakefile
95
+ - examples/docker_chat.rb
96
+ - examples/list_containers.rb
97
+ - examples/test_chat.rb
23
98
  - lib/ruby_llm/docker.rb
99
+ - lib/ruby_llm/docker/build_image.rb
100
+ - lib/ruby_llm/docker/copy_to_container.rb
101
+ - lib/ruby_llm/docker/create_container.rb
102
+ - lib/ruby_llm/docker/create_network.rb
103
+ - lib/ruby_llm/docker/create_volume.rb
104
+ - lib/ruby_llm/docker/exec_container.rb
105
+ - lib/ruby_llm/docker/fetch_container_logs.rb
106
+ - lib/ruby_llm/docker/list_containers.rb
107
+ - lib/ruby_llm/docker/list_images.rb
108
+ - lib/ruby_llm/docker/list_networks.rb
109
+ - lib/ruby_llm/docker/list_volumes.rb
110
+ - lib/ruby_llm/docker/pull_image.rb
111
+ - lib/ruby_llm/docker/push_image.rb
112
+ - lib/ruby_llm/docker/recreate_container.rb
113
+ - lib/ruby_llm/docker/remove_container.rb
114
+ - lib/ruby_llm/docker/remove_image.rb
115
+ - lib/ruby_llm/docker/remove_network.rb
116
+ - lib/ruby_llm/docker/remove_volume.rb
117
+ - lib/ruby_llm/docker/run_container.rb
118
+ - lib/ruby_llm/docker/start_container.rb
119
+ - lib/ruby_llm/docker/stop_container.rb
120
+ - lib/ruby_llm/docker/tag_image.rb
24
121
  - lib/ruby_llm/docker/version.rb
25
122
  - sig/ruby_llm/docker.rbs
26
123
  homepage: https://github.com/afstanton/ruby_llm-docker
@@ -30,6 +127,7 @@ metadata:
30
127
  allowed_push_host: https://rubygems.org
31
128
  homepage_uri: https://github.com/afstanton/ruby_llm-docker
32
129
  source_code_uri: https://github.com/afstanton/ruby_llm-docker
130
+ rubygems_mfa_required: 'true'
33
131
  rdoc_options: []
34
132
  require_paths:
35
133
  - lib
@@ -46,5 +144,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
46
144
  requirements: []
47
145
  rubygems_version: 3.7.2
48
146
  specification_version: 4
49
- summary: A Ruby gem for interacting with Docker containers directly with RubyLLM.
147
+ summary: Docker management tools for RubyLLM - comprehensive container, image, network,
148
+ and volume operations
50
149
  test_files: []