---
title: Docker
description: Run captured command lines in an existing Docker container.
icon: /images/docker-logo.svg
---

`DockerRuntime` connects to a container you started and executes every captured
line inside it. Mirage does not create, size, stop, or delete the container.
See the [Sandbox overview](/typescript/runtime/sandbox) first for routing, the
shared image, and how to serve workspace mounts inside the sandbox.

## Start the container

Live FUSE mounts need `SYS_ADMIN`, `/dev/fuse`, and the Mirage fuse image on a
Linux host:

```bash
docker run -d --cap-add SYS_ADMIN --device /dev/fuse \
  --name my-sandbox mirage-python-fuse sleep infinity
docker cp sandbox.yaml my-sandbox:/tmp/sandbox.yaml
docker exec my-sandbox mirage workspace create /tmp/sandbox.yaml
```

You can bake `sandbox.yaml` into the image instead of copying it. Sizing, GPUs,
networks, volumes, and bind mounts belong on your own `docker run` command.

## Connect from TypeScript

```ts
import { DockerRuntime, MountMode, S3Resource, Workspace } from '@struktoai/mirage-node'

const runtime = new DockerRuntime({
  captures: ['python3'],
  config: { container: 'my-sandbox' },
})
const ws = new Workspace(
  { '/data': new S3Resource({ bucket: 'my-bucket' }) },
  { mode: MountMode.EXEC, runtimes: [runtime, 'vfs'] },
)
await ws.execute('python3 job.py', { cwd: '/data' })
```

The `container` config accepts a container name or id. Unknown config fields
fail at construction. The Docker CLI is the transport, so there is no SDK or
daemon-socket integration; Docker Desktop, Colima, and a compatible Podman
alias work through the same command surface. Stdin and stderr stay separate.

<Warning>
  Mirage timeouts stop waiting for `docker exec`; they do not kill the process
  inside the container. Stop it yourself or enforce limits at the container
  layer. See [Resource limits](/typescript/runtime/sandbox#resource-limits).
</Warning>
