Disco ParrotDisco Parrot Home
Docs
Request a Demo

Set up a Local Docker host

Run sandboxes on a Docker engine you control. Register a Local Docker host, run the operator on Docker Desktop, make it your default, and turn on persistent workspaces so an agent picks up where the last run left off instead of starting clean every time.

A Local Docker host runs sandboxes on a Docker engine you control, usually Docker Desktop on your own machine, instead of on the platform's managed compute. It is the lightest way to keep agent runs on your own hardware, the natural fit for local development, and the one host that can hold a workspace on disk between runs. This page is the how-to: register the host, run the operator, make it your own, and turn on the persistence that makes it worth doing.

For the deployment choice this sits inside, when managed, Kubernetes, or Local Docker is the right answer, read sandbox hosts and deployment options. This page assumes you have decided on Local Docker.

Your machineDocker DesktopOperatorlaunches containersSandbox containersone per piece of workPersistent workspace volumeon your disk, reused between runsdials outWeb PubSubDisco Parrotsends commands backover the same channelOutbound only: the connection runs one way, from your machine to the platform
What runs where: the operator and its sandbox containers sit on your Docker engine, the workspace volume on your disk, and the operator dials out to the platform. Nothing reaches back in.

Before you start

Three things need to be in place:

  • A Docker engine you control. Docker Desktop is the usual one, on macOS, Windows, or Linux. The operator runs as a container on that engine and launches sandboxes as sibling containers, so it needs to reach the Docker socket.
  • Permission to manage hosts. Registering a host rides on the hosts.manage scope, and bringing your own host is gated by an entitlement on your workspace's plan. If you cannot see the Register host button, that is what to check with an admin.
  • Your workspace set up for bring-your-own hosts. Running an operator depends on the platform's messaging channel being configured for your workspace. When it is not, the operator bundle download is held back rather than handing you a bundle that cannot connect, so if the download is unavailable, this is the piece an admin enables first.

Register the host

Go to Platform → Sandbox Hosts and choose Register host. Pick the Local Docker operator kind, give it a name you will recognize later, your own laptop, a shared build box, and set the runtime families it should serve, the language runtimes your profiles need. The name you choose becomes the host's identifier, so pick it deliberately; it is fixed once you save. Save it.

The host appears in the list straight away as Awaiting operator. That is expected: you have created the record, but nothing is running against it yet. The next step is to bring up the operator that claims it.

add_photo_alternate
Screenshot to capture
The Register host page (a full page, not a dialog), dark theme, breadcrumb 'Platform / Sandbox Hosts / Register host'. Fields top to bottom: 'Display name' input 'priya-laptop' with a hint 'Host id will be priya-laptop and cannot change'; an optional 'Description' textarea; 'Kind' a dropdown set to 'Local Docker operator' (the open list also shows 'Kubernetes operator' and two greyed reserved entries 'Azure Container Apps operator (reserved)' and 'Custom / non-strategic'); 'Runtime families' a comma-separated text input 'node, python'; an optional 'Registration endpoint' input; a 'Tags' comma-separated input 'laptop, dev'; and an 'Identity capabilities' section with an unchecked 'Azure Workload Identity' checkbox. A primary 'Register' button and 'Cancel'.
save as: public/docs-media/sandbox-host-register-docker.png
Caption when added: Registering a Local Docker host creates the record. The display name becomes its fixed id, and the host shows Awaiting operator until the operator you run claims it.

Run the operator

A host record on its own does nothing; the operator is what actually launches containers. From the host's detail page, or its row menu, choose Download operator bundle. For a Local Docker host the bundle is a small Docker Compose project: the operator image, the mount it needs to reach your Docker socket, and a one-time key that lets it claim this host. Drop the file on the machine and bring it up the way you would any Compose project, a pull to fetch the operator image and then up to start it. The host page lists the exact commands right next to the download, so you copy rather than compose them by hand.

Once it is running, the operator dials out to the platform, claims the host, and begins checking in. Watch the host's status move from Awaiting operator to Registered, with a "last seen" that ticks over as it checks in. That is the whole handshake: you never opened a port or exposed the machine, the operator reached out and connected itself.

Register the hoststarts unregisteredDownload the bundlea Docker Compose projectRun the operatordocker compose upIt dials outclaims the host, no inboundRegisteredlast seen ticks over
The Local Docker handshake: register the host, download the Compose bundle, run the operator, and it dials out to claim the host. No port opened, no machine exposed.
add_photo_alternate
Screenshot to capture
The operator-install section of a Local Docker host detail page, dark theme. A heading 'Operator bundle' with a 'Download bundle' button and a note 'Downloading issues a fresh key and retires the previous one.' Below it an 'Apply' shell code block with the lines: 'cd ~/Downloads', 'docker compose -f ./priya-laptop-operator-compose.yaml pull', 'docker compose -f ./priya-laptop-operator-compose.yaml up -d', 'docker compose -f ./priya-laptop-operator-compose.yaml ps'. Beside it a collapsed preview of the compose file showing a service 'disco-parrot-operator', an image reference, and volume mounts including '/var/run/docker.sock:/var/run/docker.sock'. A small status line 'Credential issued 2 minutes ago'. Breadcrumb 'Platform / Sandbox Hosts / priya-laptop'.
save as: public/docs-media/local-docker-operator-bundle.png
Caption when added: The operator bundle for a Local Docker host is a Docker Compose project, with the apply commands shown next to it: pull the operator image, bring it up, confirm it is running. The bundle carries the Docker socket mount and the one-time key that claims the host.

The key is single-use

One thing worth knowing up front: the key in the bundle is single-use by design. Each time you download the bundle, the platform issues a fresh key and retires the previous one, so an old bundle stops working the moment you generate a new one. If you re-download, bring the operator up again with the new bundle, otherwise the running operator is holding a key that no longer counts and will drop off within the hour, when the short-lived token it last exchanged expires. Download once, run it, and you will not think about this again; it only matters on the day you regenerate.

Download the bundlePlatform issues key v2v2 activev1 retiredOld operator still on v1counts down, drops within the hourRun the new bundle, registered on v2Download once,run it, and younever thinkabout it again.
Why a second download quietly retires the first operator. Each bundle download issues a fresh key and retires the previous one, so an operator still running on the old key counts down and drops within the hour. Run the new bundle and it is registered again.

Make it your default

A profile can target "my Local Docker host" rather than one host by name, which is what lets a whole team share a single profile while each person's runs land on their own machine. To be the host that resolves to, open your host's detail page and choose Set as my Local Docker host.

From then on, any profile that targets the default Local Docker host launches its sandboxes on your operator when you are the one launching. Your teammate, with their own host set as theirs, gets their machine from the same profile. It is the pattern that makes Local Docker work for a team rather than only for one person: the profile is shared, the host is personal. You can set a host as yours before its operator is even running, so the preference is ready when you bring the operator up, and the Clear link unsets it whenever you want a portable profile to stop resolving to this machine.

add_photo_alternate
Screenshot to capture
The 'My Local Docker host' section of a Local Docker host detail page, dark theme. A panel titled 'Use for portable profiles' with body text 'Profiles that target your default Local Docker host will launch on this host when you start them.' A primary button 'Set as my Local Docker host' and, in a registered state, a green check with 'This is your Local Docker host' and a subtle 'Clear' link. A green 'Registered' status badge and 'Last seen 4s ago' in the page header. Breadcrumb 'Platform / Sandbox Hosts / priya-laptop'.
save as: public/docs-media/local-docker-set-default.png
Caption when added: Setting a host as yours is what makes a shared profile land on your machine. The profile targets the default Local Docker host; whose host that is resolves per person at launch.

Turn on persistent workspaces

This is the reason most people run Local Docker. A managed sandbox is disposable by design, which is exactly right for a clean run, but a fast local inner loop wants the opposite: the same checkout, the same installed dependencies, the same build cache, run after run. A Local Docker host can keep the workspace in a named Docker volume that survives a sandbox being torn down, so the next sandbox mounts the same working directory instead of rebuilding it from scratch.

Run 1installs + builds (slow)mountRun 2mounts the same checkout (seconds)mountRun 3mounts the same checkout (seconds)mountdisposable sandboxes, torn down after each runOne named persistent volumethe checkout and build cache, kept on your disk between runsThe workspace outlives the sandbox
The workspace outlives the sandbox. Each run gets a fresh, disposable sandbox, but the named volume underneath persists, so the first run pays the install-and-build cost and the rest mount the same checkout and start in seconds.

There are two sides to turning this on: the Local Docker host is what permits a workspace to persist, and a sandbox profile is where you enable it, on the profile's Maintenance tab. A profile with persistence turned on, launched on your Docker host, is what gives you the carry-over. The host's detail page then lists the persistent workspaces it is holding, each one its own volume, whether a sandbox currently has it mounted, and when it is set to expire, with controls to inspect one or clean it out when you want a fresh start. A workspace a running sandbox is using is held until that sandbox is done, so a clean-up never pulls the floor out from under live work. The volumes live on your machine, under your control, which is the other half of why this is a Local Docker feature: persistence means state on disk, and the disk is yours.

add_photo_alternate
Screenshot to capture
The persistent-workspaces section of a Local Docker host detail page, dark theme. A heading 'Persistent workspaces' with a short description and summary counts '2 retained, 0 need cleanup'. A list of two volume rows, each showing the workspace key in mono, an owner summary, a 'local driver' label, an 'in use' or 'not mounted' state chip, a 'retained' badge, a 'Created 3 days ago' line and an 'Expires in 11 days' line, and 'Inspect' + 'Clean up' buttons (Clean up disabled on the row marked 'in use'). A muted note 'Cleaning up a workspace removes only the matching operator-owned volume; the next run on that profile starts clean.' Breadcrumb 'Platform / Sandbox Hosts / priya-laptop'.
save as: public/docs-media/local-docker-persistent-volumes.png
Caption when added: The persistent workspaces the host is holding: each its own volume, whether a sandbox has it mounted right now, and when it is set to expire. Clean one up to reclaim the disk, and the next run on that profile starts fresh.

If the operator happens to be offline when you open this section, the page does not just fail; it hands you the scoped docker volume ls, docker volume inspect, and docker volume rm commands for exactly the operator-owned volumes, so you can list, inspect, or remove a workspace directly on the machine and are never locked out of your own disk.

Supply an environment file

Some local setups need a handful of values in every sandbox, a registry endpoint, a local service URL, a feature flag. A Local Docker host can point at an environment file on the machine, and the operator passes its contents into the sandboxes it launches. You give the host an absolute path to the file (a full /Users/..., C:\..., or network path), and the operator reads it when it starts a sandbox. It validates the file at that point rather than trusting it blindly, so a missing or unreadable file surfaces as a clear problem instead of silently doing nothing, and the variable names the platform reserves for cloud identity stay off-limits.

The path is treated as host configuration, so only people who can manage the host see the path itself; everyone else just sees that an environment file is configured. And because the path is something the operator is launched with, changing it means downloading a fresh bundle and bringing the operator up again. The host page flags this for you the moment the path has changed since the running operator was set up, so you are never guessing whether a restart is needed.

add_photo_alternate
Screenshot to capture
The environment-file section of a Local Docker host detail page, dark theme. A heading 'Environment file' with a path input showing '/Users/priya/dev/insights/.env.sandbox' and a 'Save' button. Below, an amber inline note with a warning icon: 'The environment file path changed. Download a fresh operator bundle and restart the operator to apply it.' and a 'Download bundle' link. Breadcrumb 'Platform / Sandbox Hosts / priya-laptop'.
save as: public/docs-media/local-docker-env-file.png
Caption when added: Point the host at an environment file and its values reach every sandbox the operator launches. Change the path and the page tells you to re-bundle and restart, so the operator and the record never quietly disagree.

Keeping it healthy

Because the operator runs on your machine, the host is healthy when the operator is running and connected, and not when it is not. The host's detail page carries a health check that names each thing the operator must be able to do, reach the Docker engine, hold permission to use it, talk to the volume API, and run the workspace-volume cleanup, so a problem points at the specific row to fix rather than a vague failure. A separate volume probe goes one step further when you want certainty: it creates and then removes a throwaway volume to prove the whole persistence path actually works, not just that the API answers. If you stop the operator, or your machine sleeps, it stops checking in and the host's last-seen goes stale; the status reflects the dropped connection, and bringing the operator back up reclaims the host on its next check-in.

Keeping the operator current is an ordinary Compose update: pull the latest image and bring the project back up. Your existing key keeps working, because it only changes when you deliberately re-download the bundle, so a routine update does not turn into a reconnection chore.

add_photo_alternate
Screenshot to capture
The health section of a Local Docker host detail page, dark theme. Two buttons, 'Check health' and 'Run volume probe' (the probe greyed unless the host is registered). An overall green 'Healthy' result and a list of check rows with their keys: 'docker-engine' green; 'docker-permission' green; 'docker-volume-api' green; 'workspace-volume-cleanup' green; 'workspace-volume-probe' green; each with a small timing. A muted timestamp 'Checked 1 minute ago'. Breadcrumb 'Platform / Sandbox Hosts / priya-laptop'.
save as: public/docs-media/local-docker-health.png
Caption when added: The health check names each thing the operator must be able to do, from reaching the Docker engine to running volume cleanup, so a red row points at the exact fix. The separate volume probe creates and removes a throwaway volume to prove the whole persistence path.

When you are done with a host for good, retiring it is a deliberate step, not a side effect. Deleting a host from the Sandbox Hosts list cleans up the operator-owned volumes and any warm capacity it held, and it tells you plainly that profiles still pointed at it will not launch until you move them, so a host never disappears out from under the work that depends on it.

add_photo_alternate
Screenshot to capture
A confirmation dialog over the Sandbox Hosts list, dark theme. Title 'Retire this host?'. Body text reads 'Deleting priya-laptop removes its operator-owned volumes and any warm capacity it was holding. This cannot be undone.' A warning row below lists '2 profiles still target this host and will not launch until you move them' with the two profile names 'Node 22 . Insights' and 'Planning . local' shown as chips. A destructive 'Retire host' primary button and a 'Cancel' secondary button. Behind it, the dimmed Sandbox Hosts list. Breadcrumb 'Platform / Sandbox Hosts'.
save as: public/docs-media/local-docker-retire-host.png
Caption when added: Retiring a host names what it removes, the operator-owned volumes and any warm capacity, and warns you plainly that profiles still pointed at it will not launch until you move them, so a host never vanishes out from under live work.

Cloud identity, when you need it

If sandboxes on your Local Docker host need to authenticate to a cloud resource as a workload identity rather than carrying a long-lived secret, the platform can issue the short-lived tokens for that, the same Azure Workload Identity model the Kubernetes host uses, adapted for the local case with a platform-run OIDC issuer. Turning it on has two preconditions:

  • The identity issuer has to be enabled for your workspace. The host will not let you check the Azure Workload Identity box until it is.
  • Each profile that wants it supplies its own Azure tenant and client id and a matching federated credential.

With those in place, a sandbox reads a short-lived projected token instead of a stored secret, so nothing long-lived ever sits on the machine. The full credential and identity model is under approved actions, and the governance view, including the platform-run OIDC issuer and what you can attest about it, is identity and cloud access; for most local development you will not need any of it, and persistent workspaces and the environment file cover the common cases.

add_photo_alternate
Screenshot to capture
The 'Identity capabilities' section of a Local Docker host detail page, dark theme. A panel titled 'Cloud identity' with a single checkbox 'Azure Workload Identity' shown disabled and greyed, a muted inline note beside it 'Enable the identity issuer for this workspace to turn this on', and a small 'Learn more' link. Below the disabled checkbox a faint preview of the per-profile fields it would bring into play: read-only placeholder rows 'Tenant id', 'Client id', and 'Federated credential', each with a small lock glyph. A green 'Registered' status badge and 'Last seen 4s ago' in the page header. Breadcrumb 'Platform / Sandbox Hosts / priya-laptop'.
save as: public/docs-media/local-docker-cloud-identity.png
Caption when added: Cloud identity stays off until the workspace issuer is enabled; the Azure Workload Identity box is greyed until then, and each profile that wants it supplies its own tenant, client id, and federated credential. Nothing long-lived sits on the machine.

Setting up Local Docker, end to end

Priya wants a fast inner loop. She is iterating on the Insights export service, and every clean sandbox spends two minutes reinstalling dependencies and warming a build before the agent does anything useful. She decides to run the work on her own machine, where the workspace can stick around.

She opens Platform → Sandbox Hosts and registers a Local Docker host named priya-laptop, with the Node and Python families her profiles use. It shows Awaiting operator. She downloads the operator bundle, a small Compose project, drops it on her laptop, and runs the pull-and-up commands the page hands her. Within a few seconds the host flips to Registered and the "last seen" starts ticking. She did not touch a firewall; the operator dialed out on its own.

She sets it as her Local Docker host, so the shared Node 22 . Insights profile, which targets the default Docker host, will land on her laptop when she launches it. Then she turns her attention to the reason she is here: she lets the host keep the workspace between runs. The first sandbox installs and builds as usual; the second mounts the same volume and starts in seconds. The agent's inner loop, which used to pay the setup cost every time, now pays it once. When she finishes the feature, she clears the persistent workspace from the host page to reclaim the disk, and the next run starts clean.

Who can set one up

Registering and managing a Local Docker host rides on hosts.manage, and bringing your own host is gated by an entitlement on your plan, so standing one up is an action for the people your workspace trusts with infrastructure. Everyone with hosts.read can see the hosts that exist and their status. Setting a host as your default Local Docker host is a personal preference rather than an administrative act, so each person chooses their own.

Why Local Docker works this way

A managed sandbox is disposable on purpose, and that is the right default: every run starts from a known state and nothing leaks from the last one. But local development has a different rhythm. The inner loop is tight, the same project over and over, and paying a clean-room setup cost on every iteration is friction with no payoff. Local Docker exists for that rhythm. It runs the same environment your team's profiles describe, on the machine in front of you, and it lets the workspace persist so the loop is fast.

The design keeps the good parts of the managed model while adding the local one. The operator reaches out rather than being reached into, so running it does not mean exposing your machine. The persistent workspace lives on your disk, under your control, so "keep my work between runs" does not mean trusting it to someone else's storage. And because the host is just another target a profile can point at, the same profile your teammates use works on your machine without a separate local configuration to maintain. You get the platform's environment with a local loop's speed, and nothing about it is a second-class version of the real thing.

For an engineer, this is the fast local loop: your Docker Desktop, your persistent workspace, the same profile the team uses, and a sandbox that starts in seconds because it kept its checkout. You stand it up once and forget the operator is there.

For a planner, nothing changes in how you work. A profile that targets the default Docker host runs on whoever launched it; you hand off work the same way, and the engineer on the other end gets their fast local environment.

For a lead, Local Docker is how a team gets a consistent local setup without a setup document that drifts. One profile, each person's own host, the same environment for everyone, and the persistence that makes local iteration quick.

For the person who owns the machine and the boundary, the operator is a well-behaved outbound client: it opens no ports, it holds the workspace on your own disk, and the key that connects it is single-use and rotates on demand. You can run agent work on your own hardware, see exactly what the operator can reach through its health check, and pull its access by stopping it.