How to Configure OpenEnv Container Providers: LocalDockerProvider, UVProvider, and KubernetesProvider

OpenEnv uses a pluggable ContainerProvider architecture that lets you run environment servers on LocalDockerProvider for local development, UVProvider for in-process execution, or KubernetesProvider for cloud-native deployments, all through a unified interface requiring only start_container, stop_container, and wait_for_ready implementations.

OpenEnv, Hugging Face's open-source environment runtime, abstracts container orchestration through a provider pattern that supports multiple backends. When you configure OpenEnv container providers, you choose how and where your environment servers execute—whether in local Docker containers, directly in the Python process via UV, or distributed across Kubernetes clusters. This guide walks through the three concrete implementations available in the codebase and how to instantiate each with EnvClient.

ContainerProvider Architecture

The foundation of OpenEnv's container abstraction is the abstract base class ContainerProvider defined in src/openenv/core/containers/runtime/providers.py. Any provider must implement three core methods:

  • start_container(image, port=None, env_vars=None, **kwargs): Launches the container or runtime and returns a base URL
  • stop_container(): Terminates the running instance and cleans up resources
  • wait_for_ready(base_url, timeout_s=30.0): Polls the /health endpoint until HTTP 200 or raises TimeoutError

This interface allows EnvClient to treat Docker, UV, and Kubernetes deployments identically, switching backends by passing a different provider instance.

LocalDockerProvider

LocalDockerProvider is the default provider when none is specified. Located in src/openenv/core/containers/runtime/providers.py, it manages single Docker containers on your development machine.

Key Behaviors

On instantiation, the provider validates that Docker is installed and accessible. When start_container is called, it:

  1. Generates a unique container name to avoid collisions
  2. Selects a free host port (or uses the supplied port argument)
  3. Executes docker run -d with the specified image and environment variables
  4. Returns http://localhost:<port> as the service endpoint

The wait_for_ready implementation polls <base_url>/health until the service responds or the timeout expires.

Usage Example

from openenv.core.env_client import EnvClient

# Defaults to LocalDockerProvider

client = EnvClient(image="echo-env:latest")
print(client.base_url)  # http://localhost:8003

client.wait_for_ready()

# ... interact with environment ...

client.close()  # Stops and removes container

UVProvider

For scenarios requiring minimal overhead, UVProvider runs the environment server directly in the current Python process using the UV async runtime. Implementation resides in src/openenv/core/containers/runtime/uv_provider.py.

Key Behaviors

Unlike Docker-based providers, UVProvider:

  • Starts the environment server in-process without containerization
  • Leverages uvloop for low-latency async request handling
  • Binds to http://127.0.0.1:<port> immediately
  • Returns instantly from wait_for_ready since the server runs synchronously in the same process

This provider eliminates Docker daemon overhead, making it ideal for high-throughput local experiments.

Usage Example

from openenv.core.env_client import EnvClient
from openenv.core.containers.runtime import UVProvider

client = EnvClient(
    image="echo-env:latest",
    provider=UVProvider()
)
print(client.base_url)  # http://127.0.0.1:8000

# Server is ready immediately

client.close()  # No container cleanup required

KubernetesProvider

For production deployments, KubernetesProvider (also in src/openenv/core/containers/runtime/providers.py) orchestrates pods and services within a Kubernetes cluster.

Key Behaviors

This provider requires a valid kubectl configuration and cluster access. During start_container:

  1. Generates a unique pod name and temporary manifest
  2. Creates a Pod resource and a NodePort Service
  3. Retrieves the node's external IP and assigned NodePort
  4. Returns http://<node-ip>:<nodeport>

The wait_for_ready method watches the Kubernetes API for pod status transitions to Ready before polling the /health endpoint.

Usage Example

from openenv.core.env_client import EnvClient
from openenv.core.containers.runtime import KubernetesProvider

provider = KubernetesProvider(namespace="openenv-demo")
client = EnvClient(
    image="echo-env:latest",
    provider=provider
)
print(client.base_url)  # http://34.12.45.67:31568

client.wait_for_ready()

# ... use environment from any cluster-accessible machine ...

client.close()  # Deletes pod and service

Provider Selection Guide

Choose your provider based on deployment constraints:

  • LocalDockerProvider: Best for standard local development with full container isolation
  • UVProvider: Optimal for running many parallel experiments on a single workstation without Docker overhead
  • KubernetesProvider: Required for cloud-native production deployments where cluster orchestration is already available

Summary

  • ContainerProvider is the abstract interface in src/openenv/core/containers/runtime/providers.py that standardizes container lifecycle management across backends.
  • LocalDockerProvider runs Docker containers locally, automatically managing ports and container names while exposing http://localhost endpoints.
  • UVProvider executes environments in-process via src/openenv/core/containers/runtime/uv_provider.py, eliminating container overhead using uvloop.
  • KubernetesProvider deploys to clusters using Pod and NodePort resources, requiring kubectl access and returning node-external URLs.
  • All providers implement start_container, stop_container, and wait_for_ready, enabling seamless switching by passing the provider instance to EnvClient.

Frequently Asked Questions

How do I switch between providers in OpenEnv?

Pass the provider instance directly to the EnvClient constructor via the provider parameter. If omitted, EnvClient defaults to LocalDockerProvider. For example, use EnvClient(image="env:latest", provider=UVProvider()) to run in-process, or supply KubernetesProvider(namespace="prod") for cluster deployment.

What are the prerequisites for KubernetesProvider?

You need a valid kubectl configuration with access to a Kubernetes cluster. The provider automatically handles pod creation, service exposure via NodePort, and resource cleanup when close() is called. Ensure your kubeconfig context points to the correct cluster before instantiation.

Can I use UVProvider in production environments?

While UVProvider offers the lowest latency for local experimentation, it lacks the isolation guarantees of containerization. For production workloads, KubernetesProvider or LocalDockerProvider provide better resource boundaries, security isolation, and scalability across nodes.

Where is the ContainerProvider interface defined?

The abstract class ContainerProvider and the concrete implementations for Docker and Kubernetes reside in src/openenv/core/containers/runtime/providers.py. The UVProvider implementation is located separately in src/openenv/core/containers/runtime/uv_provider.py, while the high-level client that consumes these providers is implemented in src/openenv/core/env_client.py.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →