Skip to main content
Glama

docker_run

Execute Docker containers with specified image, command, ports, volumes, and environment settings. Configure detach, remove, interactive, TTY, network, working directory, user, memory, CPU, and restart policy.

Instructions

Run a Docker container

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
imageYesDocker image to run
nameNoContainer name
commandNoCommand to run in container
argsNoCommand arguments
portsNoPort mappings (e.g., ["8080:80", "3000:3000"])
volumesNoVolume mounts (e.g., ["/host/path:/container/path"])
envNoEnvironment variables as key-value pairs
detachNoRun container in background
removeNoRemove container when it exits
interactiveNoKeep STDIN open
ttyNoAllocate a pseudo-TTY
networkNoNetwork to connect container to
working_dirNoWorking directory inside container
userNoUsername or UID (format: <name|uid>[:<group|gid>])
memoryNoMemory limit (e.g., "512m", "2g")
cpusNoCPU limit (e.g., "0.5", "2")
restartNoRestart policy (no, on-failure, always, unless-stopped)

Implementation Reference

  • The runContainer method is the main handler for the docker_run tool. It constructs a 'docker run' command from the provided DockerRunArgs, executes it via executeDockerCommand, and tracks detached containers by name.
    async runContainer(args: DockerRunArgs): Promise<ToolResult> {
      const { 
        image, 
        name, 
        command: cmd, 
        args: cmdArgs = [], 
        ports = [], 
        volumes = [], 
        env, 
        detach, 
        remove, 
        interactive, 
        tty, 
        network, 
        working_dir, 
        user,
        memory,
        cpus,
        restart,
        privileged,
        read_only,
        security_opt = [],
        tmpfs = [],
        ulimit = [],
        cap_add = [],
        cap_drop = [],
        device = [],
        entrypoint,
        hostname,
        init,
        label,
        log_driver,
        log_opt,
        mac_address,
        shm_size,
        stop_signal,
        stop_timeout
      } = args;
    
      ValidationUtils.validateRequired({ image }, ['image']);
    
      let command = 'docker run';
      
      if (detach) command += ' -d';
      if (remove) command += ' --rm';
      if (interactive) command += ' -i';
      if (tty) command += ' -t';
      if (name) command += ` --name ${name}`;
      if (network) command += ` --network ${network}`;
      if (working_dir) command += ` -w ${working_dir}`;
      if (user) command += ` -u ${user}`;
      if (memory) command += ` -m ${memory}`;
      if (cpus) command += ` --cpus ${cpus}`;
      if (restart) command += ` --restart ${restart}`;
      if (privileged) command += ' --privileged';
      if (read_only) command += ' --read-only';
      if (entrypoint) command += ` --entrypoint ${entrypoint}`;
      if (hostname) command += ` --hostname ${hostname}`;
      if (init) command += ' --init';
      if (mac_address) command += ` --mac-address ${mac_address}`;
      if (shm_size) command += ` --shm-size ${shm_size}`;
      if (stop_signal) command += ` --stop-signal ${stop_signal}`;
      if (stop_timeout) command += ` --stop-timeout ${stop_timeout}`;
      if (log_driver) command += ` --log-driver ${log_driver}`;
    
      // Add ports
      ports.forEach(port => command += ` -p ${port}`);
      
      // Add volumes
      volumes.forEach(volume => command += ` -v ${volume}`);
      
      // Add environment variables
      if (env) {
        for (const [key, value] of Object.entries(env)) {
          command += ` -e ${key}=${value}`;
        }
      }
    
      // Add security options
      security_opt.forEach(opt => command += ` --security-opt ${opt}`);
      
      // Add tmpfs mounts
      tmpfs.forEach(mount => command += ` --tmpfs ${mount}`);
      
      // Add ulimits
      ulimit.forEach(limit => command += ` --ulimit ${limit}`);
      
      // Add capabilities
      cap_add.forEach(cap => command += ` --cap-add ${cap}`);
      cap_drop.forEach(cap => command += ` --cap-drop ${cap}`);
      
      // Add devices
      device.forEach(dev => command += ` --device ${dev}`);
    
      // Add labels
      if (label) {
        for (const [key, value] of Object.entries(label)) {
          command += ` --label ${key}=${value}`;
        }
      }
    
      // Add log options
      if (log_opt) {
        for (const [key, value] of Object.entries(log_opt)) {
          command += ` --log-opt ${key}=${value}`;
        }
      }
    
      command += ` ${image}`;
      
      if (cmd) command += ` ${cmd}`;
      if (cmdArgs.length > 0) command += ` ${cmdArgs.join(' ')}`;
    
      try {
        const result = await this.executeDockerCommand(command, { cwd: this.getCurrentWorkspace() });
        
        // Track running containers if detached
        if (detach && name) {
          this.runningContainers.set(name, { image, started: new Date() });
        }
        
        return result;
      } catch (error: any) {
        throw new Error(`Docker run failed: ${error.message}`);
      }
    }
  • The DockerRunArgs interface defines the input schema/type for the docker_run tool, including image, name, command, ports, volumes, env, detach, remove, and many other Docker run options.
    export interface DockerRunArgs {
      image: string;
      name?: string;
      command?: string;
      args?: string[];
      ports?: string[];
      volumes?: string[];
      env?: Record<string, string>;
      detach?: boolean;
      remove?: boolean;
      interactive?: boolean;
      tty?: boolean;
      network?: string;
      working_dir?: string;
      user?: string;
      memory?: string;
      cpus?: string;
      restart?: string;
      privileged?: boolean;
      read_only?: boolean;
      security_opt?: string[];
      tmpfs?: string[];
      ulimit?: string[];
      cap_add?: string[];
      cap_drop?: string[];
      device?: string[];
      entrypoint?: string;
      hostname?: string;
      init?: boolean;
      label?: Record<string, string>;
      log_driver?: string;
      log_opt?: Record<string, string>;
      mac_address?: string;
      shm_size?: string;
      stop_signal?: string;
      stop_timeout?: number;
    }
  • src/index.ts:207-208 (registration)
    The tool registration point: when 'docker_run' is called, it routes to dockerService.runContainer() in the executeToolCommand switch statement.
    case 'docker_run':
      return await this.dockerService.runContainer(args as DockerRunArgs);
  • The tool definition (inputSchema) for docker_run, registering it as an MCP tool with all input properties (image, name, ports, volumes, env, etc.) and marking 'image' as required.
      name: 'docker_run',
      description: 'Run a Docker container',
      inputSchema: {
        type: 'object',
        properties: {
          image: { type: 'string', description: 'Docker image to run' },
          name: { type: 'string', description: 'Container name' },
          command: { type: 'string', description: 'Command to run in container' },
          args: { type: 'array', items: { type: 'string' }, description: 'Command arguments' },
          ports: { type: 'array', items: { type: 'string' }, description: 'Port mappings (e.g., ["8080:80", "3000:3000"])' },
          volumes: { type: 'array', items: { type: 'string' }, description: 'Volume mounts (e.g., ["/host/path:/container/path"])' },
          env: { type: 'object', description: 'Environment variables as key-value pairs' },
          detach: { type: 'boolean', description: 'Run container in background' },
          remove: { type: 'boolean', description: 'Remove container when it exits' },
          interactive: { type: 'boolean', description: 'Keep STDIN open' },
          tty: { type: 'boolean', description: 'Allocate a pseudo-TTY' },
          network: { type: 'string', description: 'Network to connect container to' },
          working_dir: { type: 'string', description: 'Working directory inside container' },
          user: { type: 'string', description: 'Username or UID (format: <name|uid>[:<group|gid>])' },
          memory: { type: 'string', description: 'Memory limit (e.g., "512m", "2g")' },
          cpus: { type: 'string', description: 'CPU limit (e.g., "0.5", "2")' },
          restart: { type: 'string', description: 'Restart policy (no, on-failure, always, unless-stopped)' },
        },
        required: ['image'],
      },
    },
  • The executeDockerCommand helper method that spawns a shell process, captures stdout/stderr, enforces timeouts, and returns a ToolResult. Called by runContainer to execute the constructed docker run command.
    private async executeDockerCommand(
      command: string, 
      options: any = {}, 
      timeout: number = this.defaultTimeout
    ): Promise<ToolResult> {
      return new Promise((resolve, reject) => {
        const child = spawn(command, [], {
          shell: true,
          cwd: options.cwd || this.getCurrentWorkspace(),
          env: options.env || process.env,
          stdio: ['pipe', 'pipe', 'pipe']
        });
    
        let stdout = '';
        let stderr = '';
        let isResolved = false;
        let timeoutId: NodeJS.Timeout | null = null;
    
        // Set timeout
        if (timeout > 0) {
          timeoutId = setTimeout(() => {
            if (!isResolved) {
              isResolved = true;
              child.kill('SIGTERM');
              setTimeout(() => {
                if (!child.killed) {
                  child.kill('SIGKILL');
                }
              }, 5000);
              reject(new Error(`Docker command timed out after ${timeout}ms: ${command}`));
            }
          }, timeout);
        }
    
        // Capture output with size limits
        child.stdout?.on('data', (data) => {
          const chunk = data.toString();
          stdout += chunk;
          if (stdout.length > 2 * 1024 * 1024) { // 2MB limit
            stdout = stdout.slice(-1024 * 1024) + '\n...[output truncated]...';
          }
        });
    
        child.stderr?.on('data', (data) => {
          const chunk = data.toString();
          stderr += chunk;
          if (stderr.length > 1024 * 1024) { // 1MB limit
            stderr = stderr.slice(-512 * 1024) + '\n...[error output truncated]...';
          }
        });
    
        child.on('error', (error) => {
          if (!isResolved) {
            isResolved = true;
            if (timeoutId) clearTimeout(timeoutId);
            reject(new Error(`Failed to execute Docker command: ${error.message}`));
          }
        });
    
        child.on('exit', (code, signal) => {
          if (!isResolved) {
            isResolved = true;
            if (timeoutId) clearTimeout(timeoutId);
            
            if (code === 0 || (code === null && signal === 'SIGTERM')) {
              resolve({
                content: [{
                  type: 'text',
                  text: `${stdout}${stderr ? `\nWarnings/Errors:\n${stderr}` : ''}`.trim(),
                }],
              });
            } else {
              const errorMsg = stderr || stdout || `Process exited with code ${code}`;
              reject(new Error(`Docker command failed: ${command}\n${errorMsg}`));
            }
          }
        });
      });
    }
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations and only a one-line description, the tool fails to disclose important behaviors such as image pulling, blocking vs detached execution, container cleanup policies, or output format. The description carries the full burden but provides no behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence, but it is under-specified for the tool's complexity. It does not earn its place by providing unique value; it merely repeats the name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness1/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 17 parameters, nested objects, and no output schema, the description is severely lacking. It omits return values, side effects, prerequisites, and execution behavior, making it insufficient for proper tool selection and invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with detailed descriptions for all 17 parameters. The description adds no additional meaning beyond the schema, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Run a Docker container' clearly identifies the tool's action and resource, distinguishing it from sibling tools like docker_build or docker_cleanup. However, it is a near tautology of the tool name, which slightly reduces clarity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives (e.g., docker_compose for multi-container apps) or any context about prerequisites or scenarios where it is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/agentics-ai/code-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server