Skip to content

Existing Container Support

This document describes the new feature for connecting to existing containers/pods instead of creating new ones.

Overview

LLM Sandbox now supports connecting to existing containers/pods across all backends (Docker, Kubernetes, Podman, Micromamba). This is useful for:

  • Reusing containers with complex setups: Connect to containers that already have your specific environment configured
  • Working with long-running services: Integrate with containers managed by external systems
  • Debugging and troubleshooting: Connect to running containers to debug issues
  • Performance optimization: Skip container creation and environment setup time

Usage

Basic Usage

from llm_sandbox import SandboxSession

# Connect to existing Docker container
with SandboxSession(container_id='abc123def456', lang="python") as session:
    result = session.run("print('Hello from existing container!')")
    print(result.stdout)

Docker Backend

from llm_sandbox import SandboxSession

# Connect to existing Docker container
with SandboxSession(
    container_id='your-container-id',
    lang="python",
    verbose=True
) as session:
    # Run code in existing container
    result = session.run("import sys; print(sys.version)")

    # Install additional libraries
    session.install(["numpy"])

    # Execute commands
    result = session.execute_command("ls -la")

    # Copy files
    session.copy_to_runtime("local_file.py", "/container/path/file.py")

Kubernetes Backend

from llm_sandbox import SandboxSession, SandboxBackend

# Connect to existing Kubernetes pod
with SandboxSession(
    backend=SandboxBackend.KUBERNETES,
    container_id='my-pod-name',  # Pod name
    lang="python",
    verbose=True
) as session:
    result = session.run("print('Hello from existing pod!')")

Podman Backend

from llm_sandbox import SandboxSession, SandboxBackend
from podman import PodmanClient

client = PodmanClient()
with SandboxSession(
    backend=SandboxBackend.PODMAN,
    client=client,
    container_id='podman-container-id',
    lang="python"
) as session:
    result = session.run("print('Hello from existing Podman container!')")

Important Notes

Environment Setup Skipped

When using container_id, the sandbox skips environment setup. This means:

  • No virtual environment creation (for Python)
  • No package manager initialization
  • No working directory setup
  • You must ensure the container has the proper environment and tools for your language

Container Management

  • Existing containers are not stopped/removed when the session ends
  • Only the connection is closed
  • The container continues running after session closure
  • Timeout cleanup will kill the container process but won't remove existing containers

Error Handling

from llm_sandbox import SandboxSession, ContainerError

try:
    with SandboxSession(container_id='non-existent', lang="python") as session:
        session.run("print('test')")
except ContainerError as e:
    print(f"Failed to connect: {e}")

Configuration Constraints

When using container_id:

  • Cannot use dockerfile parameter (validation error)
  • image parameter is ignored
  • Environment setup is skipped
  • Container lifecycle management is limited

Complete Example

"""Example demonstrating connecting to existing containers/pods.

This example shows how to use LLM Sandbox with existing containers instead of creating new ones.
This is useful for:
- Reusing containers with complex setups
- Working with long-running services
- Debugging and troubleshooting
- Connecting to containers managed by external systems
"""

import logging
import time

from docker import DockerClient

from llm_sandbox import SandboxBackend, SandboxSession
from llm_sandbox.exceptions import ContainerError

logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)


def create_and_setup_container() -> str:
    """Create a container with custom setup and return its ID.

    This simulates having an existing container with custom environment.

    Returns:
        str: Container ID

    """
    client = DockerClient(base_url="unix:///Users/vndee/.docker/run/docker.sock")
    logger.info("πŸš€ Creating a container with custom setup...")

    # Create a new container with custom environment
    # Use commit_container=True to save the container state
    sandbox = SandboxSession(
        client=client,
        lang="python",
        verbose=True,
        image="ghcr.io/vndee/sandbox-python-311-bullseye",
    )

    sandbox.open()

    # Install some packages and setup environment
    logger.info("πŸ“¦ Installing packages...")
    sandbox.install(["numpy", "pandas", "matplotlib"])

    # Create some files
    logger.info("πŸ“ Setting up files...")
    # Use Python code to create files instead of shell commands
    sandbox.run("""
# Create hello.py file
with open('/sandbox/hello.py', 'w') as f:
    f.write('print("Hello from existing container!")')

# Create data.txt file
with open('/sandbox/data.txt', 'w') as f:
    f.write('Custom environment data')

print("Files created successfully!")
""")

    # Verify files were created
    result = sandbox.execute_command("ls -la /sandbox/")
    logger.info("πŸ“‹ Created files:")
    logger.info(result.stdout)

    # Get container ID before closing
    container_id = sandbox.container.id
    logger.info("βœ… Container created with ID: %s...", container_id[:12])
    return str(container_id)


def demo_connect_to_existing_docker_container() -> None:
    """Demo connecting to an existing Docker container."""
    # Demo 1: Create a container for demonstration
    try:
        container_id = create_and_setup_container()
    except Exception:
        logger.exception("❌ Failed to create demo container")
        return

    logger.info("\n%s", "=" * 60)
    logger.info("🐳 Demo: Connecting to Existing Docker Container")
    logger.info("%s", "=" * 60)

    try:
        client = DockerClient(base_url="unix:///Users/vndee/.docker/run/docker.sock")
        # Connect to existing container - no environment setup needed
        with SandboxSession(client=client, container_id=container_id, lang="python", verbose=True) as sandbox:
            logger.info("βœ… Connected to existing container successfully!")

            # Run code that uses pre-installed packages
            result = sandbox.run("""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

print("Running in existing container!")
print(f"NumPy version: {np.__version__}")
print(f"Pandas version: {pd.__version__}")

# Use the pre-existing data
with open('/sandbox/data.txt', 'r') as f:
    data = f.read().strip()
    print(f"Found existing data: {data}")

# Generate some data and create a simple plot
x = np.linspace(0, 10, 100)
y = np.sin(x)

plt.figure(figsize=(8, 6))
plt.plot(x, y)
plt.title('Plot from Existing Container')
plt.xlabel('X')
plt.ylabel('sin(X)')
plt.grid(True)
plt.savefig('/sandbox/plot.png')
print("Plot saved as /sandbox/plot.png")
""")

            logger.info("πŸ“Š Code execution output:")
            logger.info(result.stdout)

            # Execute the pre-existing script
            result = sandbox.execute_command("python /sandbox/hello.py")
            logger.info("πŸ“ Pre-existing script output:")
            logger.info(result.stdout)

            # List files to show existing content
            result = sandbox.execute_command("ls -la /sandbox/")
            logger.info("πŸ“ Container contents:")
            logger.info(result.stdout)

    except ContainerError:
        logger.exception("❌ Failed to connect to container")
    except Exception:
        logger.exception("❌ Unexpected error")


def demo_connect_to_existing_kubernetes_pod() -> None:
    """Demo connecting to an existing Kubernetes pod."""
    logger.info("\n%s", "=" * 60)
    logger.info("☸️  Demo: Connecting to Existing Kubernetes Pod")
    logger.info("%s", "=" * 60)

    # For demo purposes, we'll create a pod first
    # In practice, you would have a pod already running
    try:
        # First create a pod (simulating existing pod)
        logger.info("πŸ“¦ Creating a demo pod (simulating existing pod)...")
        sandbox = SandboxSession(backend=SandboxBackend.KUBERNETES, lang="python", verbose=True)
        sandbox.open()
        pod_id = sandbox.container  # Get pod name

        # Setup some environment
        sandbox.execute_command("echo 'Pod environment ready' > /sandbox/pod_info.txt")
        logger.info("βœ… Demo pod created: %s", pod_id)

        # Now connect to the "existing" pod
        logger.info("πŸ”— Connecting to existing pod: %s", pod_id)

        # Connect to the existing pod
        with SandboxSession(
            backend=SandboxBackend.KUBERNETES,
            container_id=pod_id,  # Connect to existing pod
            lang="python",
            verbose=True,
        ) as sandbox:
            logger.info("βœ… Connected to existing pod successfully!")

            # Run code in the existing pod
            result = sandbox.run("""
import sys
print(f"Python version: {sys.version}")
print("Running in existing Kubernetes pod!")

# Read the existing file
try:
    with open('/sandbox/pod_info.txt', 'r') as f:
        info = f.read().strip()
        print(f"Pod info: {info}")
except FileNotFoundError:
    print("Pod info file not found")

# Show current working directory
import os
print(f"Current directory: {os.getcwd()}")
print(f"Directory contents: {os.listdir('/sandbox')}")
""")

            logger.info("πŸ“Š Pod execution output:")
            logger.info(result.stdout)

    except ContainerError:
        logger.exception("❌ Failed to connect to pod")
    except Exception:
        logger.exception("❌ Error in Kubernetes demo (cluster may not be available)")


def demo_connect_to_existing_podman_container() -> None:
    """Demo connecting to an existing Podman container."""
    logger.info("\n%s", "=" * 60)
    logger.info("🦭 Demo: Connecting to Existing Podman Container")
    logger.info("%s", "=" * 60)

    try:
        from podman import PodmanClient

        client = PodmanClient(
            base_url="unix:///var/folders/lh/rjbzw60n1fv7xr9kffn7gr840000gn/T/podman/podman-machine-default-api.sock"
        )

        # First create a container (simulating existing container)
        logger.info("πŸ“¦ Creating a demo Podman container...")
        sandbox = SandboxSession(
            backend=SandboxBackend.PODMAN, client=client, lang="python", verbose=True, keep_template=True
        )
        sandbox.open()
        container_id = sandbox.container.id

        # Setup some environment
        sandbox.run("""
with open('/sandbox/podman_info.txt', 'w') as f:
    f.write('Podman environment ready')
""")
        logger.info("βœ… Demo Podman container created: %s...", container_id[:12])

        # Connect to the existing container
        logger.info("πŸ”— Connecting to existing Podman container...")
        with SandboxSession(
            backend=SandboxBackend.PODMAN, client=client, container_id=container_id, lang="python", verbose=True
        ) as sandbox:
            logger.info("βœ… Connected to existing Podman container successfully!")

            # Run code in the existing container
            result = sandbox.run("""
import platform
print(f"Platform: {platform.platform()}")
print("Running in existing Podman container!")

# Read the existing file
try:
    with open('/sandbox/podman_info.txt', 'r') as f:
        info = f.read().strip()
        print(f"Container info: {info}")
except FileNotFoundError:
    print("Container info file not found")
""")

            logger.info("πŸ“Š Podman execution output:")
            logger.info(result.stdout)

    except ImportError:
        logger.warning("⚠️  Podman not available, skipping Podman demo")
    except ContainerError:
        logger.exception("❌ Failed to connect to Podman container")
    except Exception:
        logger.exception("❌ Error in Podman demo")


def demo_error_handling() -> None:
    """Demo error handling when connecting to non-existent containers."""
    logger.info("\n%s", "=" * 60)
    logger.info("πŸ›‘οΈ  Demo: Error Handling")
    logger.info("%s", "=" * 60)

    # Try connecting to non-existent container
    logger.info("πŸ§ͺ Testing connection to non-existent container...")
    try:
        with SandboxSession(container_id="non-existent-container-id", lang="python", verbose=True) as sandbox:
            sandbox.run("print('This should not work')")

    except ContainerError:
        logger.info("βœ… Correctly caught ContainerError")
    except Exception:
        logger.exception("❌ Unexpected error type")

    # Try with invalid pod name
    logger.info("πŸ§ͺ Testing connection to non-existent pod...")
    try:
        with SandboxSession(
            backend=SandboxBackend.KUBERNETES, container_id="non-existent-pod", lang="python", verbose=True
        ) as sandbox:
            sandbox.run("print('This should not work')")

    except ContainerError:
        logger.info("βœ… Correctly caught ContainerError for K8s")
    except Exception:
        logger.exception("⚠️  K8s error (cluster may not be available)")


def main() -> None:
    """Run all demos."""
    logger.info("🎯 LLM Sandbox - Existing Container Support Demo")
    logger.info("=" * 80)
    logger.info("This demo shows how to connect to existing containers/pods")
    logger.info("instead of creating new ones from scratch.")
    logger.info("=" * 80)

    # Give container a moment to settle
    time.sleep(2)

    # Demo 1: Connect to existing Docker container
    demo_connect_to_existing_docker_container()

    # Demo 2: Connect to existing Kubernetes pod
    demo_connect_to_existing_kubernetes_pod()

    # # Demo 3: Connect to existing Podman container
    demo_connect_to_existing_podman_container()

    # Demo 4: Error handling
    demo_error_handling()

    logger.info("\n%s", "=" * 80)
    logger.info("πŸŽ‰ Demo completed!")
    logger.info("Key benefits of existing container support:")
    logger.info("β€’ πŸš€ Faster startup (no environment setup)")
    logger.info("β€’ πŸ”§ Work with pre-configured environments")
    logger.info("β€’ πŸ”„ Reuse containers across multiple sandboxs")
    logger.info("β€’ πŸ› Connect to running containers for debugging")
    logger.info("β€’ πŸ“¦ Integrate with external container management")
    logger.info("=" * 80)


if __name__ == "__main__":
    main()

Backend-Specific Notes

Docker

  • Uses container ID or name
  • Supports both running and stopped containers (will start if stopped)
  • Full Docker API compatibility

Kubernetes

  • Uses pod name as container_id
  • Must specify correct namespace via kube_namespace parameter
  • Pod must be in "Running" state
  • Will wait briefly for "Pending" pods to start

Podman

  • Uses container ID or name
  • Compatible with Docker API
  • Supports both running and stopped containers

Best Practices

  1. Ensure Environment Readiness: Make sure containers have required interpreters/compilers
  2. Handle Connection Errors: Always wrap in try/catch for ContainerError
  3. Document Dependencies: Clearly document what your existing containers need
  4. Test Connectivity: Verify container is accessible before production use
  5. Monitor Resources: Existing containers may have different resource constraints