ruby_llm-docker 0.2.5 → 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.
- checksums.yaml +4 -4
- data/examples/docker_chat.rb +41 -0
- data/lib/ruby_llm/docker/build_image.rb +64 -65
- data/lib/ruby_llm/docker/copy_to_container.rb +89 -134
- data/lib/ruby_llm/docker/create_container.rb +64 -86
- data/lib/ruby_llm/docker/create_network.rb +63 -79
- data/lib/ruby_llm/docker/create_volume.rb +57 -79
- data/lib/ruby_llm/docker/exec_container.rb +94 -111
- data/lib/ruby_llm/docker/fetch_container_logs.rb +63 -85
- data/lib/ruby_llm/docker/list_containers.rb +46 -40
- data/lib/ruby_llm/docker/list_images.rb +34 -55
- data/lib/ruby_llm/docker/list_networks.rb +35 -57
- data/lib/ruby_llm/docker/list_volumes.rb +35 -64
- data/lib/ruby_llm/docker/pull_image.rb +24 -48
- data/lib/ruby_llm/docker/push_image.rb +60 -89
- data/lib/ruby_llm/docker/recreate_container.rb +47 -79
- data/lib/ruby_llm/docker/remove_container.rb +48 -76
- data/lib/ruby_llm/docker/remove_image.rb +53 -95
- data/lib/ruby_llm/docker/remove_network.rb +42 -78
- data/lib/ruby_llm/docker/remove_volume.rb +52 -85
- data/lib/ruby_llm/docker/run_container.rb +73 -53
- data/lib/ruby_llm/docker/start_container.rb +35 -58
- data/lib/ruby_llm/docker/stop_container.rb +40 -66
- data/lib/ruby_llm/docker/tag_image.rb +67 -95
- data/lib/ruby_llm/docker/version.rb +10 -1
- data/lib/ruby_llm/docker.rb +13 -0
- metadata +15 -1
|
@@ -2,110 +2,72 @@
|
|
|
2
2
|
|
|
3
3
|
module RubyLLM
|
|
4
4
|
module Docker
|
|
5
|
-
#
|
|
5
|
+
# MCP tool for removing Docker networks.
|
|
6
6
|
#
|
|
7
|
-
# This tool provides the ability to
|
|
8
|
-
#
|
|
9
|
-
#
|
|
7
|
+
# This tool provides the ability to delete Docker networks when they
|
|
8
|
+
# are no longer needed. Network removal helps maintain clean network
|
|
9
|
+
# configurations and prevents resource leaks.
|
|
10
10
|
#
|
|
11
11
|
# == Features
|
|
12
12
|
#
|
|
13
|
-
# - Remove
|
|
14
|
-
# -
|
|
13
|
+
# - Remove networks by ID or name
|
|
14
|
+
# - Validation of network existence
|
|
15
15
|
# - Comprehensive error handling
|
|
16
|
-
# -
|
|
16
|
+
# - Prevention of removing networks in use
|
|
17
17
|
# - Safe cleanup of network resources
|
|
18
|
-
#
|
|
19
|
-
# == ⚠️ Service Disruption Warning ⚠️
|
|
20
|
-
#
|
|
21
|
-
# **NETWORK REMOVAL CAN DISRUPT SERVICES**
|
|
22
|
-
#
|
|
23
|
-
# Removing networks can cause immediate service disruption:
|
|
24
|
-
# - Connected containers lose network connectivity
|
|
25
|
-
# - Inter-container communication is broken
|
|
26
|
-
# - Services may become unreachable
|
|
27
|
-
# - Application functionality can be severely impacted
|
|
28
|
-
# - Network-dependent processes may fail
|
|
29
|
-
#
|
|
30
|
-
# == Protected Networks
|
|
31
|
-
#
|
|
32
|
-
# Docker protects certain built-in networks from removal:
|
|
33
|
-
# - **bridge**: Default bridge network
|
|
34
|
-
# - **host**: Host networking
|
|
35
|
-
# - **none**: No networking
|
|
36
|
-
# - **System networks**: Docker-managed networks
|
|
18
|
+
# - Network dependency checking
|
|
37
19
|
#
|
|
38
20
|
# == Security Considerations
|
|
39
21
|
#
|
|
40
|
-
# Network removal
|
|
41
|
-
# -
|
|
42
|
-
# -
|
|
43
|
-
# -
|
|
44
|
-
# -
|
|
22
|
+
# Network removal involves important considerations:
|
|
23
|
+
# - **Service Disruption**: Removing active networks disconnects containers
|
|
24
|
+
# - **Data Isolation**: Network removal can affect container communication
|
|
25
|
+
# - **Resource Cleanup**: Improper removal can leave network artifacts
|
|
26
|
+
# - **Container Dependencies**: Containers may fail without expected networks
|
|
27
|
+
# - **Network Policies**: Removal affects security and access policies
|
|
45
28
|
#
|
|
46
|
-
# Security
|
|
47
|
-
# -
|
|
48
|
-
# -
|
|
49
|
-
# -
|
|
50
|
-
# -
|
|
29
|
+
# **Security Recommendations**:
|
|
30
|
+
# - Verify no containers are connected before removal
|
|
31
|
+
# - Check for dependent services and applications
|
|
32
|
+
# - Document network removal in change logs
|
|
33
|
+
# - Implement network lifecycle management
|
|
34
|
+
# - Monitor for orphaned network resources
|
|
35
|
+
# - Use network removal as part of cleanup procedures
|
|
51
36
|
#
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
# -
|
|
55
|
-
# - Have rollback plans for critical networks
|
|
56
|
-
# - Document network removal procedures
|
|
57
|
-
# - Monitor network connectivity after removal
|
|
37
|
+
# == Parameters
|
|
38
|
+
#
|
|
39
|
+
# - **id**: Network ID or name (required)
|
|
58
40
|
#
|
|
59
41
|
# == Example Usage
|
|
60
42
|
#
|
|
61
|
-
# # Remove
|
|
62
|
-
# RemoveNetwork.call(
|
|
43
|
+
# # Remove network by name
|
|
44
|
+
# response = RemoveNetwork.call(
|
|
63
45
|
# server_context: context,
|
|
64
46
|
# id: "app-network"
|
|
65
47
|
# )
|
|
66
48
|
#
|
|
67
|
-
# # Remove by
|
|
68
|
-
# RemoveNetwork.call(
|
|
49
|
+
# # Remove network by ID
|
|
50
|
+
# response = RemoveNetwork.call(
|
|
69
51
|
# server_context: context,
|
|
70
52
|
# id: "abc123def456"
|
|
71
53
|
# )
|
|
72
54
|
#
|
|
73
|
-
#
|
|
74
|
-
#
|
|
75
|
-
#
|
|
55
|
+
# # Clean up test networks
|
|
56
|
+
# response = RemoveNetwork.call(
|
|
57
|
+
# server_context: context,
|
|
58
|
+
# id: "test-isolated-network"
|
|
59
|
+
# )
|
|
60
|
+
#
|
|
61
|
+
# @see ::Docker::Network#delete
|
|
76
62
|
# @since 0.1.0
|
|
77
|
-
|
|
63
|
+
REMOVE_NETWORK_DEFINITION = ToolForge.define(:remove_network) do
|
|
78
64
|
description 'Remove a Docker network'
|
|
79
65
|
|
|
80
|
-
param :id,
|
|
66
|
+
param :id,
|
|
67
|
+
type: :string,
|
|
68
|
+
description: 'Network ID or name'
|
|
81
69
|
|
|
82
|
-
|
|
83
|
-
#
|
|
84
|
-
# This method permanently deletes the specified network. The network
|
|
85
|
-
# must not have any containers connected to it, and built-in system
|
|
86
|
-
# networks cannot be removed.
|
|
87
|
-
#
|
|
88
|
-
# @param id [String] network ID or name to remove
|
|
89
|
-
# @param server_context [Object] RubyLLM context (unused but required)
|
|
90
|
-
#
|
|
91
|
-
# @return [RubyLLM::Tool::Response] removal operation results
|
|
92
|
-
#
|
|
93
|
-
# @raise [Docker::Error::NotFoundError] if network doesn't exist
|
|
94
|
-
# @raise [StandardError] for removal failures or dependency conflicts
|
|
95
|
-
#
|
|
96
|
-
# @example Remove custom network
|
|
97
|
-
# response = RemoveNetwork.call(
|
|
98
|
-
# server_context: context,
|
|
99
|
-
# id: "frontend-network"
|
|
100
|
-
# )
|
|
101
|
-
#
|
|
102
|
-
# @example Remove by ID
|
|
103
|
-
# response = tool.execute(
|
|
104
|
-
# id: "1a2b3c4d5e6f"
|
|
105
|
-
# )
|
|
106
|
-
#
|
|
107
|
-
# @see Docker::Network#delete
|
|
108
|
-
def execute(id:)
|
|
70
|
+
execute do |id:|
|
|
109
71
|
network = ::Docker::Network.get(id)
|
|
110
72
|
network.delete
|
|
111
73
|
|
|
@@ -116,5 +78,7 @@ module RubyLLM
|
|
|
116
78
|
"Error removing network: #{e.message}"
|
|
117
79
|
end
|
|
118
80
|
end
|
|
81
|
+
|
|
82
|
+
RemoveNetwork = REMOVE_NETWORK_DEFINITION.to_ruby_llm_tool
|
|
119
83
|
end
|
|
120
84
|
end
|
|
@@ -2,117 +2,82 @@
|
|
|
2
2
|
|
|
3
3
|
module RubyLLM
|
|
4
4
|
module Docker
|
|
5
|
-
#
|
|
5
|
+
# MCP tool for removing Docker volumes.
|
|
6
6
|
#
|
|
7
|
-
# This tool provides the ability to
|
|
8
|
-
#
|
|
9
|
-
#
|
|
7
|
+
# This tool provides the ability to delete Docker volumes when they
|
|
8
|
+
# are no longer needed. Volume removal is critical for preventing
|
|
9
|
+
# storage leaks and maintaining clean Docker environments.
|
|
10
10
|
#
|
|
11
11
|
# == Features
|
|
12
12
|
#
|
|
13
|
-
# - Remove
|
|
14
|
-
# - Force removal
|
|
13
|
+
# - Remove volumes by name
|
|
14
|
+
# - Force removal of volumes in use
|
|
15
|
+
# - Validation of volume existence
|
|
15
16
|
# - Comprehensive error handling
|
|
16
|
-
# -
|
|
17
|
-
# -
|
|
18
|
-
#
|
|
19
|
-
# == ⚠️ CRITICAL DATA LOSS WARNING ⚠️
|
|
20
|
-
#
|
|
21
|
-
# **DESTRUCTIVE OPERATION - PERMANENT DATA LOSS**
|
|
22
|
-
#
|
|
23
|
-
# This operation permanently and irreversibly deletes data:
|
|
24
|
-
# - **ALL DATA** in the volume is deleted forever
|
|
25
|
-
# - No recovery possible after deletion
|
|
26
|
-
# - Applications may lose critical data
|
|
27
|
-
# - Databases and persistent state are destroyed
|
|
28
|
-
# - Configuration files and user data are lost
|
|
29
|
-
# - Operation cannot be undone
|
|
30
|
-
#
|
|
31
|
-
# == Volume Dependencies
|
|
32
|
-
#
|
|
33
|
-
# Volumes may have active dependencies:
|
|
34
|
-
# - **Running Containers**: Containers currently using the volume
|
|
35
|
-
# - **Stopped Containers**: Containers that could be restarted
|
|
36
|
-
# - **Application Data**: Critical application state and databases
|
|
37
|
-
# - **User Data**: User-generated content and files
|
|
17
|
+
# - Safe volume cleanup procedures
|
|
18
|
+
# - Prevention of accidental data loss
|
|
38
19
|
#
|
|
39
20
|
# == Security Considerations
|
|
40
21
|
#
|
|
41
|
-
# Volume removal
|
|
42
|
-
# -
|
|
43
|
-
# -
|
|
44
|
-
# -
|
|
45
|
-
# -
|
|
22
|
+
# Volume removal involves critical data considerations:
|
|
23
|
+
# - **Data Loss**: Removed volumes and their data are permanently deleted
|
|
24
|
+
# - **Service Disruption**: Removing volumes can break running containers
|
|
25
|
+
# - **Data Recovery**: Volume data cannot be recovered after removal
|
|
26
|
+
# - **Container Dependencies**: Applications may fail without expected volumes
|
|
27
|
+
# - **Storage Cleanup**: Improper removal can leave orphaned data
|
|
28
|
+
# - **Backup Requirements**: Critical data should be backed up before removal
|
|
46
29
|
#
|
|
47
|
-
#
|
|
48
|
-
# -
|
|
49
|
-
# - Verify no containers
|
|
50
|
-
# -
|
|
51
|
-
# -
|
|
52
|
-
# -
|
|
30
|
+
# **Security Recommendations**:
|
|
31
|
+
# - Always backup critical data before volume removal
|
|
32
|
+
# - Verify no containers are using the volume
|
|
33
|
+
# - Use force option only when absolutely necessary
|
|
34
|
+
# - Document volume removal in change management
|
|
35
|
+
# - Implement volume lifecycle and retention policies
|
|
36
|
+
# - Monitor storage usage after volume removal
|
|
37
|
+
# - Consider data migration instead of removal
|
|
53
38
|
#
|
|
54
|
-
# ==
|
|
39
|
+
# == Parameters
|
|
55
40
|
#
|
|
56
|
-
#
|
|
57
|
-
# -
|
|
58
|
-
# - Can cause immediate application failures
|
|
59
|
-
# - May corrupt running applications
|
|
60
|
-
# - Data loss occurs immediately
|
|
41
|
+
# - **name**: Volume name (required)
|
|
42
|
+
# - **force**: Force removal of the volume (optional, default: false)
|
|
61
43
|
#
|
|
62
44
|
# == Example Usage
|
|
63
45
|
#
|
|
64
|
-
# #
|
|
65
|
-
# RemoveVolume.call(
|
|
46
|
+
# # Remove unused volume
|
|
47
|
+
# response = RemoveVolume.call(
|
|
66
48
|
# server_context: context,
|
|
67
|
-
# name: "
|
|
49
|
+
# name: "old-app-data"
|
|
68
50
|
# )
|
|
69
51
|
#
|
|
70
|
-
# # Force
|
|
71
|
-
# RemoveVolume.call(
|
|
52
|
+
# # Force remove volume in use
|
|
53
|
+
# response = RemoveVolume.call(
|
|
72
54
|
# server_context: context,
|
|
73
55
|
# name: "stuck-volume",
|
|
74
56
|
# force: true
|
|
75
57
|
# )
|
|
76
58
|
#
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
#
|
|
59
|
+
# # Clean up test volumes
|
|
60
|
+
# response = RemoveVolume.call(
|
|
61
|
+
# server_context: context,
|
|
62
|
+
# name: "test-data-volume"
|
|
63
|
+
# )
|
|
64
|
+
#
|
|
65
|
+
# @see ::Docker::Volume#remove
|
|
80
66
|
# @since 0.1.0
|
|
81
|
-
|
|
67
|
+
REMOVE_VOLUME_DEFINITION = ToolForge.define(:remove_volume) do
|
|
82
68
|
description 'Remove a Docker volume'
|
|
83
69
|
|
|
84
|
-
param :name,
|
|
85
|
-
|
|
70
|
+
param :name,
|
|
71
|
+
type: :string,
|
|
72
|
+
description: 'Volume name'
|
|
86
73
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
# @param server_context [Object] RubyLLM context (unused but required)
|
|
95
|
-
# @param force [Boolean] whether to force removal despite dependencies (default: false)
|
|
96
|
-
#
|
|
97
|
-
# @return [RubyLLM::Tool::Response] removal operation results
|
|
98
|
-
#
|
|
99
|
-
# @raise [Docker::Error::NotFoundError] if volume doesn't exist
|
|
100
|
-
# @raise [StandardError] for removal failures or dependency conflicts
|
|
101
|
-
#
|
|
102
|
-
# @example Remove unused volume
|
|
103
|
-
# response = RemoveVolume.call(
|
|
104
|
-
# server_context: context,
|
|
105
|
-
# name: "old-cache-data"
|
|
106
|
-
# )
|
|
107
|
-
#
|
|
108
|
-
# @example Force remove problematic volume
|
|
109
|
-
# response = tool.execute(
|
|
110
|
-
# name: "corrupted-volume",
|
|
111
|
-
# force: true
|
|
112
|
-
# )
|
|
113
|
-
#
|
|
114
|
-
# @see Docker::Volume#remove
|
|
115
|
-
def execute(name:, force: false)
|
|
74
|
+
param :force,
|
|
75
|
+
type: :boolean,
|
|
76
|
+
description: 'Force removal of the volume (default: false)',
|
|
77
|
+
required: false,
|
|
78
|
+
default: false
|
|
79
|
+
|
|
80
|
+
execute do |name:, force: false|
|
|
116
81
|
volume = ::Docker::Volume.get(name)
|
|
117
82
|
volume.remove(force: force)
|
|
118
83
|
|
|
@@ -123,5 +88,7 @@ module RubyLLM
|
|
|
123
88
|
"Error removing volume: #{e.message}"
|
|
124
89
|
end
|
|
125
90
|
end
|
|
91
|
+
|
|
92
|
+
RemoveVolume = REMOVE_VOLUME_DEFINITION.to_ruby_llm_tool
|
|
126
93
|
end
|
|
127
94
|
end
|
|
@@ -2,87 +2,105 @@
|
|
|
2
2
|
|
|
3
3
|
module RubyLLM
|
|
4
4
|
module Docker
|
|
5
|
-
#
|
|
5
|
+
# MCP tool for running Docker containers.
|
|
6
6
|
#
|
|
7
|
-
# This tool
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
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
11
|
#
|
|
12
12
|
# == Features
|
|
13
13
|
#
|
|
14
|
-
# -
|
|
15
|
-
# -
|
|
16
|
-
# -
|
|
17
|
-
# -
|
|
18
|
-
# -
|
|
19
|
-
# -
|
|
20
|
-
# - Comprehensive error handling
|
|
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
|
|
21
20
|
#
|
|
22
21
|
# == Security Considerations
|
|
23
22
|
#
|
|
24
|
-
#
|
|
25
|
-
# -
|
|
26
|
-
# -
|
|
27
|
-
# -
|
|
28
|
-
# -
|
|
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
29
|
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
# -
|
|
35
|
-
# -
|
|
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)
|
|
36
40
|
#
|
|
37
41
|
# == Example Usage
|
|
38
42
|
#
|
|
39
|
-
# # Simple container
|
|
40
|
-
# RunContainer.call(
|
|
43
|
+
# # Simple container execution
|
|
44
|
+
# response = RunContainer.call(
|
|
41
45
|
# server_context: context,
|
|
42
|
-
# image: "
|
|
43
|
-
#
|
|
46
|
+
# image: "alpine:latest",
|
|
47
|
+
# cmd: "echo 'Hello World'"
|
|
44
48
|
# )
|
|
45
49
|
#
|
|
46
|
-
# #
|
|
47
|
-
# RunContainer.call(
|
|
50
|
+
# # Web server with port binding
|
|
51
|
+
# response = RunContainer.call(
|
|
48
52
|
# server_context: context,
|
|
49
|
-
# image: "
|
|
50
|
-
# name: "
|
|
51
|
-
#
|
|
53
|
+
# image: "nginx:latest",
|
|
54
|
+
# name: "web-server",
|
|
55
|
+
# exposed_ports: {"80/tcp" => {}},
|
|
52
56
|
# host_config: {
|
|
53
|
-
# "PortBindings" => {"
|
|
54
|
-
# "Binds" => ["/host/data:/var/lib/postgresql/data"]
|
|
57
|
+
# "PortBindings" => {"80/tcp" => [{"HostPort" => "8080"}]}
|
|
55
58
|
# }
|
|
56
59
|
# )
|
|
57
60
|
#
|
|
58
|
-
# @see
|
|
59
|
-
# @see StartContainer
|
|
60
|
-
# @see Docker::Container.create
|
|
61
|
+
# @see ::Docker::Container.create
|
|
61
62
|
# @since 0.1.0
|
|
62
|
-
|
|
63
|
+
RUN_CONTAINER_DEFINITION = ToolForge.define(:run_container) do
|
|
63
64
|
description 'Run a Docker container (create and start)'
|
|
64
65
|
|
|
65
|
-
param :image,
|
|
66
|
-
|
|
67
|
-
|
|
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
|
+
|
|
68
80
|
param :env,
|
|
69
|
-
|
|
70
|
-
|
|
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)',
|
|
71
88
|
required: false
|
|
72
|
-
param :exposed_ports, desc: 'Exposed ports as JSON object (optional)', required: false
|
|
73
|
-
param :host_config, desc: 'Host configuration including port bindings, volumes, etc.',
|
|
74
|
-
required: false
|
|
75
89
|
|
|
76
|
-
|
|
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|
|
|
77
96
|
config = { 'Image' => image }
|
|
78
97
|
config['name'] = name if name
|
|
79
|
-
config['Cmd'] = cmd if cmd
|
|
80
98
|
|
|
81
|
-
# Parse
|
|
82
|
-
if
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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?
|
|
86
104
|
|
|
87
105
|
config['ExposedPorts'] = exposed_ports if exposed_ports
|
|
88
106
|
config['HostConfig'] = host_config if host_config
|
|
@@ -100,5 +118,7 @@ module RubyLLM
|
|
|
100
118
|
"Error running container: #{e.message}"
|
|
101
119
|
end
|
|
102
120
|
end
|
|
121
|
+
|
|
122
|
+
RunContainer = RUN_CONTAINER_DEFINITION.to_ruby_llm_tool
|
|
103
123
|
end
|
|
104
124
|
end
|
|
@@ -2,87 +2,62 @@
|
|
|
2
2
|
|
|
3
3
|
module RubyLLM
|
|
4
4
|
module Docker
|
|
5
|
-
#
|
|
5
|
+
# MCP tool for starting Docker containers.
|
|
6
6
|
#
|
|
7
|
-
# This tool
|
|
8
|
-
#
|
|
9
|
-
# and
|
|
10
|
-
# containers.
|
|
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.
|
|
11
10
|
#
|
|
12
11
|
# == Features
|
|
13
12
|
#
|
|
14
|
-
# -
|
|
15
|
-
# -
|
|
16
|
-
# -
|
|
17
|
-
# -
|
|
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
|
|
18
19
|
#
|
|
19
20
|
# == Security Considerations
|
|
20
21
|
#
|
|
21
|
-
# Starting containers
|
|
22
|
-
# -
|
|
23
|
-
# -
|
|
24
|
-
# -
|
|
25
|
-
# -
|
|
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
|
|
26
27
|
#
|
|
27
|
-
# Ensure
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
# -
|
|
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
|
|
32
36
|
#
|
|
33
37
|
# == Example Usage
|
|
34
38
|
#
|
|
35
|
-
# # Start container
|
|
36
|
-
# StartContainer.call(
|
|
39
|
+
# # Start by container name
|
|
40
|
+
# response = StartContainer.call(
|
|
37
41
|
# server_context: context,
|
|
38
42
|
# id: "web-server"
|
|
39
43
|
# )
|
|
40
44
|
#
|
|
41
|
-
# # Start container
|
|
42
|
-
# StartContainer.call(
|
|
45
|
+
# # Start by container ID
|
|
46
|
+
# response = StartContainer.call(
|
|
43
47
|
# server_context: context,
|
|
44
48
|
# id: "a1b2c3d4e5f6"
|
|
45
49
|
# )
|
|
46
50
|
#
|
|
47
|
-
# @see
|
|
48
|
-
# @see StopContainer
|
|
49
|
-
# @see RunContainer
|
|
50
|
-
# @see Docker::Container#start
|
|
51
|
+
# @see ::Docker::Container#start
|
|
51
52
|
# @since 0.1.0
|
|
52
|
-
|
|
53
|
+
START_CONTAINER_DEFINITION = ToolForge.define(:start_container) do
|
|
53
54
|
description 'Start a Docker container'
|
|
54
55
|
|
|
55
|
-
param :id,
|
|
56
|
+
param :id,
|
|
57
|
+
type: :string,
|
|
58
|
+
description: 'Container ID or name'
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
#
|
|
59
|
-
# This method starts a container that is currently in a stopped state.
|
|
60
|
-
# The container must already exist and be in a startable state. If the
|
|
61
|
-
# container is already running, Docker will typically ignore the start
|
|
62
|
-
# command without error.
|
|
63
|
-
#
|
|
64
|
-
# @param id [String] container ID (full or short) or container name
|
|
65
|
-
# @param server_context [Object] RubyLLM context (unused but required)
|
|
66
|
-
#
|
|
67
|
-
# @return [RubyLLM::Tool::Response] start operation results
|
|
68
|
-
#
|
|
69
|
-
# @raise [Docker::Error::NotFoundError] if container doesn't exist
|
|
70
|
-
# @raise [StandardError] for other start failures
|
|
71
|
-
#
|
|
72
|
-
# @example Start by container name
|
|
73
|
-
# response = StartContainer.call(
|
|
74
|
-
# server_context: context,
|
|
75
|
-
# id: "my-app-container"
|
|
76
|
-
# )
|
|
77
|
-
#
|
|
78
|
-
# @example Start by container ID
|
|
79
|
-
# response = StartContainer.call(
|
|
80
|
-
# server_context: context,
|
|
81
|
-
# id: "abc123def456"
|
|
82
|
-
# )
|
|
83
|
-
#
|
|
84
|
-
# @see Docker::Container#start
|
|
85
|
-
def execute(id:)
|
|
60
|
+
execute do |id:|
|
|
86
61
|
container = ::Docker::Container.get(id)
|
|
87
62
|
container.start
|
|
88
63
|
|
|
@@ -93,5 +68,7 @@ module RubyLLM
|
|
|
93
68
|
"Error starting container: #{e.message}"
|
|
94
69
|
end
|
|
95
70
|
end
|
|
71
|
+
|
|
72
|
+
StartContainer = START_CONTAINER_DEFINITION.to_ruby_llm_tool
|
|
96
73
|
end
|
|
97
74
|
end
|