Execute Docker Command
execute_docker_commandRun Docker commands through natural language or direct input to manage containers, images, and system operations.
Instructions
Execute Docker commands using natural language or direct commands
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | Natural language command or direct Docker command to execute |
Implementation Reference
- src/index.ts:1158-1195 (registration)Registration of the 'execute_docker_command' MCP tool, including schema and inline handler function.
server.registerTool( "execute_docker_command", { title: "Execute Docker Command", description: "Execute Docker commands using natural language or direct commands", inputSchema: { command: z.string().describe("Natural language command or direct Docker command to execute") } }, async ({ command }) => { try { // Parse natural language to Docker command const dockerCommand = parseDockerCommand(command); // Execute the Docker command const result = await executeDockerCommand(dockerCommand); return { content: [ { type: "text", text: `Executed: ${dockerCommand}\n\nOutput:\n${result.stdout}${result.stderr ? `\nErrors:\n${result.stderr}` : ""}` } ] }; } catch (error) { return { content: [ { type: "text", text: `Error executing Docker command: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } } ); - src/index.ts:1167-1195 (handler)Handler function for execute_docker_command tool: parses input with parseDockerCommand, executes via executeDockerCommand, and formats response.
async ({ command }) => { try { // Parse natural language to Docker command const dockerCommand = parseDockerCommand(command); // Execute the Docker command const result = await executeDockerCommand(dockerCommand); return { content: [ { type: "text", text: `Executed: ${dockerCommand}\n\nOutput:\n${result.stdout}${result.stderr ? `\nErrors:\n${result.stderr}` : ""}` } ] }; } catch (error) { return { content: [ { type: "text", text: `Error executing Docker command: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } } ); - src/index.ts:1160-1165 (schema)Input schema definition for the execute_docker_command tool using Zod.
{ title: "Execute Docker Command", description: "Execute Docker commands using natural language or direct commands", inputSchema: { command: z.string().describe("Natural language command or direct Docker command to execute") } - src/index.ts:383-390 (helper)Core helper function executeDockerCommand that runs shell commands using Node's child_process.exec (promisified). Used by the tool handler and throughout the codebase.
async function executeDockerCommand(command: string): Promise<{ stdout: string; stderr: string }> { try { const result = await execAsync(command); return result; } catch (error: any) { throw new Error(`Docker command failed: ${error.message}`); } } - src/index.ts:393-723 (helper)parseDockerCommand helper: Converts natural language descriptions (e.g., 'list running containers') to exact Docker CLI commands via regex pattern matching.
function parseDockerCommand(naturalLanguage: string): string { const input = naturalLanguage.toLowerCase().trim(); // === CONTAINER OPERATIONS === // List containers with various formats if (input.match(/(list|show|display|get)\s+(all\s+)?(containers?|running|stopped)/)) { if (input.includes("all") || input.includes("stopped")) { return "docker ps -a"; } if (input.includes("running")) { return "docker ps"; } return "docker ps -a"; } if (input.match(/(what|which)\s+containers?\s+are\s+(running|active)/)) { return "docker ps"; } // Container lifecycle operations if (input.match(/(start|run|launch)\s+(container\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(start|run|launch)\s+(?:container\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker start ${match[2]}`; } } if (input.match(/(stop|halt|kill)\s+(container\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(stop|halt|kill)\s+(?:container\s+)?([a-zA-Z0-9_-]+)/); if (match) { const action = match[1] === "kill" ? "kill" : "stop"; return `docker ${action} ${match[3]}`; } } if (input.match(/(restart|reboot)\s+(container\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(restart|reboot)\s+(?:container\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker restart ${match[3]}`; } } if (input.match(/(remove|delete|rm)\s+(container\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(remove|delete|rm)\s+(?:container\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker rm ${match[3]}`; } } // Container inspection and logs if (input.match(/(inspect|examine|details?)\s+(container\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(inspect|examine|details?)\s+(?:container\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker inspect ${match[3]}`; } } if (input.match(/(logs?|output)\s+(from\s+)?(container\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(logs?|output)\s+(?:from\s+)?(?:container\s+)?([a-zA-Z0-9_-]+)/); if (match) { const follow = input.includes("follow") || input.includes("tail") ? " -f" : ""; const lines = input.match(/(\d+)\s+lines?/) ? ` --tail ${input.match(/(\d+)\s+lines?/)![1]}` : ""; return `docker logs${follow}${lines} ${match[2]}`; } } if (input.match(/(exec|execute|run)\s+(in|into)\s+(container\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(exec|execute|run)\s+(?:in|into)\s+(?:container\s+)?([a-zA-Z0-9_-]+)/); if (match) { const command = input.includes("bash") ? "bash" : input.includes("sh") ? "sh" : "bash"; return `docker exec -it ${match[2]} ${command}`; } } // === IMAGE OPERATIONS === // List images if (input.match(/(list|show|display|get)\s+(all\s+)?(images?|repos?|repositories)/)) { if (input.includes("dangling")) { return "docker images -f dangling=true"; } return "docker images"; } // Pull images if (input.match(/(pull|download|fetch)\s+(image\s+)?([a-zA-Z0-9/_.-]+)(:([a-zA-Z0-9._-]+))?/)) { const match = input.match(/(pull|download|fetch)\s+(?:image\s+)?([a-zA-Z0-9/_.-]+)(?::([a-zA-Z0-9._-]+))?/); if (match) { const image = match[2]; const tag = match[3] || (input.includes("latest") ? "latest" : ""); return `docker pull ${image}${tag ? `:${tag}` : ""}`; } } // Push images if (input.match(/(push|upload)\s+(image\s+)?([a-zA-Z0-9/_.-]+)(:([a-zA-Z0-9._-]+))?/)) { const match = input.match(/(push|upload)\s+(?:image\s+)?([a-zA-Z0-9/_.-]+)(?::([a-zA-Z0-9._-]+))?/); if (match) { const image = match[2]; const tag = match[3] || ""; return `docker push ${image}${tag ? `:${tag}` : ""}`; } } // Build images if (input.match(/(build|create)\s+(image\s+)?([a-zA-Z0-9/_.-]+)/)) { const match = input.match(/(build|create)\s+(?:image\s+)?([a-zA-Z0-9/_.-]+)/); if (match) { const dockerfile = input.includes("dockerfile") ? ` -f ${input.match(/dockerfile[:\s]+([^\s]+)/)?.[1] || "Dockerfile"}` : ""; const context = input.match(/(?:from|in)\s+([^\s]+)/) ? ` ${input.match(/(?:from|in)\s+([^\s]+)/)![1]}` : " ."; return `docker build${dockerfile} -t ${match[3]}${context}`; } } // Remove images if (input.match(/(remove|delete|rm)\s+(image\s+)?([a-zA-Z0-9/_.-]+)/)) { const match = input.match(/(remove|delete|rm)\s+(?:image\s+)?([a-zA-Z0-9/_.-]+)/); if (match) { const force = input.includes("force") ? " -f" : ""; return `docker rmi${force} ${match[3]}`; } } // Tag images if (input.match(/(tag|label)\s+(image\s+)?([a-zA-Z0-9/_.-]+)\s+(as\s+)?([a-zA-Z0-9/_.-]+)/)) { const match = input.match(/(tag|label)\s+(?:image\s+)?([a-zA-Z0-9/_.-]+)\s+(?:as\s+)?([a-zA-Z0-9/_.-]+)/); if (match) { return `docker tag ${match[2]} ${match[3]}`; } } // === VOLUME OPERATIONS === if (input.match(/(list|show|display)\s+(all\s+)?(volumes?|storage)/)) { if (input.includes("dangling")) { return "docker volume ls -f dangling=true"; } return "docker volume ls"; } if (input.match(/(create|make)\s+(volume\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(create|make)\s+(?:volume\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker volume create ${match[2]}`; } } if (input.match(/(remove|delete)\s+(volume\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(remove|delete)\s+(?:volume\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker volume rm ${match[3]}`; } } if (input.match(/(inspect|examine)\s+(volume\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(inspect|examine)\s+(?:volume\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker volume inspect ${match[3]}`; } } // === NETWORK OPERATIONS === if (input.match(/(list|show|display)\s+(all\s+)?(networks?|networking)/)) { return "docker network ls"; } if (input.match(/(create|make)\s+(network\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(create|make)\s+(?:network\s+)?([a-zA-Z0-9_-]+)/); if (match) { const driver = input.includes("bridge") ? " --driver bridge" : input.includes("overlay") ? " --driver overlay" : ""; return `docker network create${driver} ${match[2]}`; } } if (input.match(/(remove|delete)\s+(network\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(remove|delete)\s+(?:network\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker network rm ${match[3]}`; } } if (input.match(/(connect|attach)\s+([a-zA-Z0-9_-]+)\s+(to\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(connect|attach)\s+([a-zA-Z0-9_-]+)\s+(?:to\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker network connect ${match[3]} ${match[2]}`; } } if (input.match(/(disconnect|detach)\s+([a-zA-Z0-9_-]+)\s+(from\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(disconnect|detach)\s+([a-zA-Z0-9_-]+)\s+(?:from\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker network disconnect ${match[4]} ${match[2]}`; } } // === SYSTEM OPERATIONS === if (input.match(/(system\s+)?(info|information|details)/)) { return "docker system info"; } if (input.match(/(version|ver)/)) { return "docker --version && docker-compose --version"; } if (input.match(/(stats|statistics|status|monitor)/)) { const noStream = !input.includes("follow") && !input.includes("continuous"); return `docker stats${noStream ? " --no-stream" : ""}`; } if (input.match(/(disk\s+usage|space|storage\s+usage)/)) { const verbose = input.includes("verbose") || input.includes("detailed") ? " -v" : ""; return `docker system df${verbose}`; } if (input.match(/(clean\s*up?|prune|cleanup)/)) { if (input.includes("all") || input.includes("everything")) { return "docker system prune -a -f"; } if (input.includes("volumes")) { return "docker system prune --volumes -f"; } return "docker system prune -f"; } // === DOCKER COMPOSE OPERATIONS === if (input.match(/(compose\s+)?(up|start|launch)/)) { const detached = !input.includes("foreground") && !input.includes("attached"); const build = input.includes("build") || input.includes("rebuild"); const service = input.match(/service\s+([a-zA-Z0-9_-]+)/) ? ` ${input.match(/service\s+([a-zA-Z0-9_-]+)/)![1]}` : ""; return `docker-compose up${detached ? " -d" : ""}${build ? " --build" : ""}${service}`; } if (input.match(/(compose\s+)?(down|stop|halt)/)) { const volumes = input.includes("volumes") || input.includes("data") ? " --volumes" : ""; const images = input.includes("images") ? " --rmi all" : ""; return `docker-compose down${volumes}${images}`; } if (input.match(/(compose\s+)?(logs|output)/)) { const follow = input.includes("follow") || input.includes("tail") ? " -f" : ""; const service = input.match(/(?:from\s+|service\s+)([a-zA-Z0-9_-]+)/) ? ` ${input.match(/(?:from\s+|service\s+)([a-zA-Z0-9_-]+)/)![1]}` : ""; return `docker-compose logs${follow}${service}`; } if (input.match(/(compose\s+)?(ps|status|services)/)) { return "docker-compose ps"; } if (input.match(/(compose\s+)?(restart|reboot)/)) { const service = input.match(/service\s+([a-zA-Z0-9_-]+)/) ? ` ${input.match(/service\s+([a-zA-Z0-9_-]+)/)![1]}` : ""; return `docker-compose restart${service}`; } if (input.match(/(compose\s+)?(build|rebuild)/)) { const service = input.match(/service\s+([a-zA-Z0-9_-]+)/) ? ` ${input.match(/service\s+([a-zA-Z0-9_-]+)/)![1]}` : ""; const noCache = input.includes("fresh") || input.includes("clean") ? " --no-cache" : ""; return `docker-compose build${noCache}${service}`; } // === ADVANCED OPERATIONS === // Search Docker Hub if (input.match(/(search|find)\s+(for\s+)?([a-zA-Z0-9/_.-]+)/)) { const match = input.match(/(search|find)\s+(?:for\s+)?([a-zA-Z0-9/_.-]+)/); if (match) { return `docker search ${match[2]}`; } } // Copy files if (input.match(/(copy|cp)\s+([^\s]+)\s+(from|to)\s+([a-zA-Z0-9_-]+)/)) { const match = input.match(/(copy|cp)\s+([^\s]+)\s+(from|to)\s+([a-zA-Z0-9_-]+)/); if (match) { const [, , path, direction, container] = match; if (direction === "from") { return `docker cp ${container}:${path} .`; } else { return `docker cp ${path} ${container}:/tmp/`; } } } // Port mapping info if (input.match(/(port|ports)\s+(of\s+|for\s+)?([a-zA-Z0-9_-]+)/)) { const match = input.match(/(port|ports)\s+(?:of\s+|for\s+)?([a-zA-Z0-9_-]+)/); if (match) { return `docker port ${match[2]}`; } } // Process list in container if (input.match(/(processes?|ps|top)\s+(in|inside)\s+([a-zA-Z0-9_-]+)/)) { const match = input.match(/(processes?|ps|top)\s+(?:in|inside)\s+([a-zA-Z0-9_-]+)/); if (match) { return `docker top ${match[3]}`; } } // === REGISTRY OPERATIONS === if (input.match(/login\s+(to\s+)?([a-zA-Z0-9._-]+)?/)) { const match = input.match(/login\s+(?:to\s+)?([a-zA-Z0-9._-]+)?/); const registry = match?.[1] || ""; return `docker login${registry ? ` ${registry}` : ""}`; } if (input.match(/logout\s+(from\s+)?([a-zA-Z0-9._-]+)?/)) { const match = input.match(/logout\s+(?:from\s+)?([a-zA-Z0-9._-]+)?/); const registry = match?.[1] || ""; return `docker logout${registry ? ` ${registry}` : ""}`; } // === FALLBACK === // If no pattern matches but it starts with docker, pass through if (input.startsWith("docker")) { return input; } // General help if (input.match(/(help|usage|commands)/)) { return "docker --help"; } // Default to treating as direct docker command return `docker ${input}`; }