langchain-docker-backend
Docker sandbox backend for AI agents — execute code safely in isolated containers.
Installation
pip install langchain-docker-backend
Prerequisites: Docker must be installed and running. The default image below works out of the box — pull it before first use:
docker pull ghcr.io/astral-sh/uv:python3.13-bookworm-slim
💡 Any Docker image works.
ghcr.io/astral-sh/uv:python3.13-bookworm-slimis just the default. You can use any image —python:3.13-slim,ubuntu:22.04,node:20, or your own custom image. Pass it viaimage=to match your runtime needs.
Connecting to Docker
DockerSandbox connects to Docker via docker.from_env(). By default it reads the DOCKER_HOST environment variable, falling back to the local Unix socket (/var/run/docker.sock).
Local Docker (default)
The most common setup — your code runs on the host and connects to the local Docker daemon. No extra configuration needed:
sandbox = DockerSandbox() # connects to /var/run/docker.sock
Docker-in-Docker
When running the library itself inside a container, there are two approaches:
Approach 1 — Socket mount (Docker outside of Docker)
Mount the host's Docker socket into the container. The container shares the host's Docker daemon — simpler and more lightweight:
docker run -v /var/run/docker.sock:/var/run/docker.sock your-image
# Inside the container — works the same way
sandbox = DockerSandbox()
Note: This gives the container access to the host's Docker daemon. Make sure the security implications are acceptable for your use case.
Approach 2 — True Docker-in-Docker (DinD)
Run a full Docker daemon inside the container using the docker:dind image. Completely isolated from the host's Docker, but requires --privileged:
docker run --privileged docker:dind
# Inside the DinD container — point to the inner daemon
sandbox = DockerSandbox(
docker_client_kwargs={"base_url": "unix:///var/run/docker.sock"}
)
Note:
--privilegedgrants the container extended Linux capabilities. Prefer the socket mount approach unless you need full isolation between the inner and outer Docker daemons.
Remote Docker
Connect to a Docker daemon on another machine via TCP.
Option 1: Environment variable (recommended)
export DOCKER_HOST=tcp://192.168.1.100:2375
sandbox = DockerSandbox() # reads DOCKER_HOST automatically
Option 2: Explicit docker_client_kwargs
sandbox = DockerSandbox(
docker_client_kwargs={"base_url": "tcp://192.168.1.100:2375"}
)
With TLS:
import docker.tls
sandbox = DockerSandbox(
docker_client_kwargs={
"base_url": "tcp://192.168.1.100:2376",
"tls": docker.tls.TLSConfig(
ca_cert="/path/to/ca.pem",
client_cert=("/path/to/cert.pem", "/path/to/key.pem"),
),
}
)
Usage
deepagents
Plug DockerSandbox into a deep agent — the agent gets a full set of sandbox tools and runs code in an isolated container:
from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_docker_backend import DockerSandbox
sandbox = DockerSandbox()
try:
agent = create_deep_agent(
model=ChatAnthropic(model="claude-sonnet-4-6"),
system_prompt="You are a coding assistant with sandbox access.",
backend=sandbox,
)
result = agent.invoke({
"messages": [{"role": "user", "content": "Write and run a fizzbuzz script"}]
})
print(result)
finally:
sandbox.close()
LangChain
With LangChain, wire it through FilesystemMiddleware:
from langchain.agents import create_agent
from langchain_anthropic import ChatAnthropic
from deepagents.middleware.filesystem import FilesystemMiddleware
from langchain_docker_backend import DockerSandbox
sandbox = DockerSandbox()
try:
agent = create_agent(
model=ChatAnthropic(model="claude-sonnet-4-6"),
middleware=[FilesystemMiddleware(backend=sandbox)],
)
result = agent.invoke({
"messages": [{"role": "user", "content": "Write a fizzbuzz script and run it"}]
})
finally:
sandbox.close()
Direct Usage
Beyond agent use, you can interact with the sandbox directly — execute commands, read and write files, list directories, edit file content.
Pick any image to suit your stack:
sandbox = DockerSandbox(image="python:3.13-slim") # bare Python
sandbox = DockerSandbox(image="node:20") # Node.js
sandbox = DockerSandbox(image="ubuntu:22.04") # Ubuntu
sandbox = DockerSandbox() # default (uv + Python 3.13)
from langchain_docker_backend import DockerSandbox
sandbox = DockerSandbox()
try:
# Execute commands
result = sandbox.execute("echo 'Hello from Docker!'")
print(result.output) # Hello from Docker!
print(result.exit_code) # 0
# Write a file
sandbox.write("/workspace/test.txt", "Hello, World!")
# Read it back
file = sandbox.read("/workspace/test.txt")
print(file.file_data["content"]) # Hello, World!
# List a directory
ls = sandbox.ls("/workspace")
for entry in ls.entries:
print(entry["path"], entry.get("is_dir", False))
# Find and replace
sandbox.edit("/workspace/test.txt", "Hello", "你好")
# Upload / download binary files
sandbox.upload_files([("data.bin", b"\x00\x01\x02")])
files = sandbox.download_files(["data.bin"])
print(files[0].content) # b'\x00\x01\x02'
# Commands time out
result = sandbox.execute("sleep 10", timeout=2)
print(result.exit_code) # 124
finally:
sandbox.close()
Network & Hardware Configuration
Network, DNS, GPU and resource settings are applied when the container is created:
from langchain_docker_backend import DockerSandbox
with DockerSandbox(
network_mode="host", # "bridge" (Docker default), "host", "none", "container:<id>"
dns=["1.1.1.1", "8.8.8.8"], # custom DNS servers
gpus="all", # "all" or a number of GPUs
container_kwargs={ # any other docker-py containers.run() option
"mem_limit": "4g",
"nano_cpus": 2_000_000_000, # 2 CPUs
"shm_size": "2g",
"devices": ["/dev/accel0:/dev/accel0"], # pass through host devices
},
) as sandbox:
sandbox.execute("pip install requests")
- No internet inside the sandbox? Containers on Docker's default
bridgenetwork already have outbound access. If package installs or web requests fail, DNS is the usual cause (e.g. a host using127.0.0.53and a network that blocks Docker's8.8.8.8fallback) — setdns=[...]to resolvers reachable from your network before reaching fornetwork_mode="host". - GPUs require the NVIDIA Container Toolkit on the host. Other accelerators (NPUs, TPUs, ...) can be exposed via
container_kwargs={"devices": [...]}or{"device_requests": [...]}. - Isolation:
network_mode="host", hostdevicesandcontainer_kwargs={"privileged": True}weaken the sandbox boundary. Usenetwork_mode="none"for fully offline agents.
Design
DockerSandbox implements BaseSandbox, which defines a full set of sandbox operations — synchronous and asynchronous — including execute, file reads and writes, directory listing, glob, grep, and more.
When plugged into FilesystemMiddleware or create_deep_agent(backend=...), most operations are exposed as tools that the agent model decides when to invoke: the model autonomously chooses to ls a directory, read_file, write_file, execute a command, etc.
The exception is upload_files and download_files. These remain developer-only — the developer controls what data enters the sandbox and what results to extract, not the model.
API Reference
DockerSandbox
| Parameter | Type | Default | Description |
|---|---|---|---|
image |
str |
ghcr.io/astral-sh/uv:python3.13-bookworm-slim |
Any Docker image (public, private, or custom) |
container_name |
str | None |
auto-generated | Container name |
volumes |
dict |
{} |
Volume mounts |
working_dir |
str |
/workspace |
Working directory inside container |
auto_remove |
bool |
True |
Remove container on close |
execute_timeout |
int |
120 |
Default timeout in seconds |
max_output_bytes |
int |
512000 |
Max output bytes before truncation |
docker_client_kwargs |
dict | None |
None |
Extra keyword arguments for docker.from_env() (e.g. base_url, tls) |
network_mode |
str | None |
None (Docker default bridge) |
Container network mode: "bridge", "host", "none", "container:<id>" |
dns |
list[str] | None |
None |
Custom DNS servers |
gpus |
int | str | None |
None |
GPUs to expose: "all" or a positive count (needs NVIDIA Container Toolkit) |
container_kwargs |
dict | None |
None |
Extra keyword arguments for client.containers.run() (e.g. mem_limit, nano_cpus, devices, shm_size) |
Key Methods
| Method | Description |
|---|---|
execute(command, *, timeout) |
Run a shell command |
write(path, content) |
Write a text file |
read(path) |
Read a text file |
ls(path) |
List directory contents |
edit(path, find, replace) |
Find and replace in a file |
upload_files(files) |
Upload binary files (tar-based) |
download_files(paths) |
Download binary files (tar-based) |
close() |
Stop and optionally remove container |
ExecuteResponse
| Field | Type | Description |
|---|---|---|
output |
str |
Combined stdout + stderr |
exit_code |
int |
Command exit code |
truncated |
bool |
Whether output was truncated |
Metadata
Release files for langchain-docker-backend 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| langchain_docker_backend-1.1.0.tar.gz | 113.6 kB | With provenance | Details for langchain_docker_backend-1.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| langchain_docker_backend-1.1.0-py3-none-any.whl | Python 3 | none | any | Details for langchain_docker_backend-1.1.0-py3-none-any.whl |
Total release size: 124.7 kB
Release files / langchain_docker_backend-1.1.0.tar.gz
| Download URL | langchain_docker_backend-1.1.0.tar.gz |
|---|---|
| Size | 113.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9dca54afd9ce0ae3d698ea3eba2e9f114f0d5360d38af1f80d96fb80feee3cf4
|
|
BLAKE2b-256 checksum How to use checksums |
7421fc604da4d3d46682f029c8bcddf45cffa32cab681e2ec94d32fd079f043a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logRelease files / langchain_docker_backend-1.1.0-py3-none-any.whl
| Download URL | langchain_docker_backend-1.1.0-py3-none-any.whl |
|---|---|
| Size | 11.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
93e1f28c9f7e2c090e7b7b7d3ff7551f7e63e97456da1041367190ea98898490
|
|
BLAKE2b-256 checksum How to use checksums |
bf68e32faf297dc448d55b2f239be9e7addb481c812b7295d4e976943cf3dd08
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logSecurity for langchain-docker-backend 1.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for langchain_docker_backend-1.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.