Skip to main content

A Python client for Enroot

Project description

enroot-py

A Python client library for Enroot, providing a docker-py inspired interface for managing Enroot containers and images.

Overview

enroot-py offers a Pythonic API to interact with Enroot, NVIDIA's container runtime for HPC environments. It provides a familiar interface similar to docker-py, making it easy to manage containers, pull images, and execute commands within Enroot containers.

Features

  • Image Management: Pull, list, and retrieve Docker images converted to Enroot's .sqsh format
  • Container Operations: Create, start, stop, remove, and execute commands in containers
  • Port Mapping: Automatic port allocation and mapping for containerized services
  • Environment Variables: Pass environment variables to containers
  • Resource Limits: CPU and memory limits via systemd-run (when available)
  • Docker Compatibility: Automatically imports Docker images if not found locally

Prerequisites

  • Python 3.8 or higher
  • Enroot installed and available in your PATH
  • Linux operating system (Enroot is Linux-only)

Installation

This library is not yet packaged on PyPI. To use it, clone the repository and add it to your PYTHONPATH:

git clone https://github.com/your-username/enroot-py.git
cd enroot-py
export PYTHONPATH=$PYTHONPATH:$(pwd)

Alternatively, you can install it in development mode:

pip install -e .

Quick Start

Creating a Client

from enroot.client import from_env

client = from_env()

# Check if Enroot is available
if client.ping():
    print("Enroot is running!")

Working with Images

Pulling an Image

Pull a Docker image and convert it to Enroot's .sqsh format:

# Pull with explicit tag
image = client.images.pull("ubuntu", "20.04")
print(f"Pulled image: {image.id}")

# Pull latest tag (default)
image = client.images.pull("python", "3.9")

# Pull from a custom registry
image = client.images.pull("my-image", "latest", registry_host="registry.example.com")

Listing Images

images = client.images.list()
for image in images:
    print(f"Image: {image.id}, Tags: {image.tags}")

Getting a Specific Image

image = client.images.get("ubuntu+20.04")  # Use '+' instead of '/' or ':'
print(f"Found image: {image.id}")

Working with Containers

Starting a Container

container = client.containers.run(
    "ubuntu:20.04",              # Image name (will be imported if needed)
    command="sleep 3600",        # Command to run
    name="my-container",         # Optional container name
    detach=True,                 # Required: must be True
    ports={"8080/tcp": "8080"},  # Port mapping (container_port: host_port)
    environment={                # Environment variables
        "MY_VAR": "my_value",
        "DEBUG": "1"
    },
    cpu_count=2.0,              # Optional: CPU limit (requires systemd-run)
    mem_limit="2G"              # Optional: Memory limit (requires systemd-run)
)
print(f"Started container: {container.name}")
print(f"Status: {container.status}")

Note: detach=True is required. Non-detached mode is not currently supported.

Using Local .sqsh Files

You can also use local .sqsh files directly:

container = client.containers.run(
    "/path/to/image.sqsh",
    command="bash",
    detach=True
)

Listing Containers

containers = client.containers.list()
for container in containers:
    print(f"- {container.name} ({container.status})")

Getting a Container

container = client.containers.get("my-container")
print(f"Container status: {container.status}")
print(f"Container attributes: {container.attrs}")

Executing Commands in a Container

result = container.exec_run("echo 'Hello from container!'")
print(f"Exit code: {result.exit_code}")
print(f"Output: {result.output}")

# Execute with a list of arguments
result = container.exec_run(["ls", "-la", "/tmp"])

Stopping and Removing Containers

# Stop (kill) a container
container.kill()

# Remove a container
container.remove()

# Force remove a container
container.remove(force=True)

Checking Container Status

# Reload status from Enroot
container.reload()

# Get current status
status = container.status  # "running" or "exited"

# Get container attributes (including port mappings)
attrs = container.attrs

Configuration

Environment Variables

  • ENROOT_HOME: Override the default Enroot home directory (default: ~/.cache/enroot)
  • ENROOT_DEBUG: Set to "1" to enable debug output (shows Enroot command execution)
  • XDG_CACHE_HOME: Used for cache directory if ENROOT_HOME is not set

Port Mapping

When you specify ports in containers.run(), the library automatically allocates a free port on the host and maps it to the container port. The allocated port is available in the container's attrs:

container = client.containers.run(
    "nginx",
    detach=True,
    ports={"80/tcp": "80"}
)

# Access port mapping
port_mapping = container.attrs["NetworkSettings"]["Ports"]
# The actual host port is stored here

The allocated port is also set as the PORT environment variable inside the container.

Resource Limits

CPU and memory limits are applied using systemd-run when available:

container = client.containers.run(
    "my-image",
    detach=True,
    cpu_count=1.5,      # 1.5 CPUs
    mem_limit="512M"    # 512 MB memory limit
)

Note: Resource limits require systemd-run to be available. If it's not found, a warning is issued and the limits are ignored.

API Reference

EnrootClient

Main client class for interacting with Enroot.

  • ping() -> bool: Check if Enroot is available
  • images: Access to image operations (Images instance)
  • containers: Access to container operations (Containers instance)

Images

Image management operations.

  • pull(repository: str, tag: str | None = None, registry_host: str = "docker.io") -> Image: Pull and import a Docker image
  • list() -> List[Image]: List all available images
  • get(ref: str) -> Image: Get a specific image by reference

Containers

Container management operations.

  • run(image, command=None, name=None, *, detach=False, remove=False, ports=None, environment=None, cpu_count=None, mem_limit=None, cpus=None, **_) -> Container: Run a new container
  • list() -> List[Container]: List all containers
  • get(ident: str) -> Container: Get a container by name

Container

Represents a single container instance.

  • name: str: Container name
  • status: str: Container status ("running" or "exited")
  • attrs: Dict: Container attributes (similar to Docker API)
  • reload(): Reload container status from Enroot
  • kill(**_): Stop and remove the container
  • remove(force: bool = False, **_): Remove the container
  • exec_run(cmd: str | List[str], **_) -> ExecResult: Execute a command in the container

Image

Represents a container image.

  • id: str: Image ID (path to .sqsh file)
  • tags: List[str]: Image tags

Limitations

  • Detached Mode Only: The detach parameter must be True. Non-detached containers are not supported.
  • No Logs: The logs() method returns an empty bytes object. Enroot doesn't provide a built-in logging mechanism.
  • Resource Limits: CPU and memory limits require systemd-run to be available on the system.
  • Port Mapping: All ports are mapped to a single automatically-allocated free port. Individual port mappings are not fully supported.

Testing

Run the test suite:

python -m unittest discover tests

Or run individual test files:

python -m unittest tests.test_client
python -m unittest tests.test_container
python -m unittest tests.test_image
python -m unittest tests.test_utils

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License (see pyproject.toml for details)

Related Projects

  • Enroot - The underlying container runtime
  • docker-py - The inspiration for this library's API design

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

enroot_py-0.1.0.tar.gz (24.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

enroot_py-0.1.0-py3-none-any.whl (21.8 kB view details)

Uploaded Python 3

File details

Details for the file enroot_py-0.1.0.tar.gz.

File metadata

  • Download URL: enroot_py-0.1.0.tar.gz
  • Upload date:
  • Size: 24.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for enroot_py-0.1.0.tar.gz
Algorithm Hash digest
SHA256 14c92a3ecb255b591a2dc7521455e2644819cac27f28c53f34a558f6dce5daa8
MD5 ceb92b4d8564657a8a094f7add0f5b1f
BLAKE2b-256 3f8c5a03416a9b12226f1a4f4bf7392f5de2d91040230da46f938d71f7399cd0

See more details on using hashes here.

File details

Details for the file enroot_py-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: enroot_py-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 21.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for enroot_py-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c9406a1997787cb5176a0317286b47c573b02809f7f488b120317bce1d0897f0
MD5 c66616ec856c4fab94c57ba2a6d61663
BLAKE2b-256 eec6ce0b2e64368be1beb95455d2b5624cfcd4471f3ba45f9bfc566ba6e477fa

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page