cloudflare / cloudflare/containers

Containers local dev on WSL2 (kernel 6.18.x): app container never created, only egress proxy-everything sidecar; 'Container failed to start'

Open
#231 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
270
Forks
42
Avg merge
1d 5h
Merged PRs (30d)
4

Description

## Summary

Running a `@cloudflare/sandbox` container in **local dev on WSL2 (kernel 6.18.x)** never starts the container. Miniflare/workerd builds the image and starts the egress `cloudflare/proxy-everything` sidecar, but the **actual app container is never created**. The readiness probe to the container aborts and workerd throws `kj/timer.c++:30: overloaded: operation timed out`, surfacing as **`Container failed to start`**. Deployed/remote containers are unaffected — this is local-dev only.

## Expected vs actual

- **Expected:** `getSandbox(env.SANDBOX, id).exec("echo hi")` starts the container and returns.
- **Actual:** the call hangs ~100s; the DO retries; only a `workerd----proxy` container exists in `docker ps` — the app container (`cloudflare-dev/:`) is never created. Fails with `Container failed to start`.

## Dev-server output

```
{ level: 'info', message: 'Using http transport', component: 'sandbox-do', ... }
Error checking if container is ready: The operation was aborted (x4)
e = kj/timer.c++:30: overloaded: operation timed out
; sentryErrorContext = jsgInternalError; wdErrId = ...
{ level: 'error', message: 'Sandbox error', error: { message: 'Container failed to start' } }
{ level: 'warn', message: 'container.startup', outcome: 'unrecognized_error', error: 'Container failed to start' }
{ level: 'info', message: 'Container not ready, retrying', status: 503, attempt: N }
```

## Minimal reproduction

`wrangler.jsonc`
```jsonc
{
"name": "sbx-repro",
"main": "src/index.ts",
"compatibility_date": "2026-07-01",
"containers": [{ "class_name": "Sandbox", "image": "./Dockerfile", "instance_type": "basic", "max_instances": 1 }],
"durable_objects": { "bindings": [{ "name": "SANDBOX", "class_name": "Sandbox" }] },
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["Sandbox"] }]
}
```

`Dockerfile`
```dockerfile
FROM docker.io/cloudflare/sandbox:0.12.3
```

`src/index.ts`
```ts
import { getSandbox } from "@cloudflare/sandbox";
export { Sandbox } from "@cloudflare/sandbox";

export default {
async fetch(_req: Request, env: { SANDBOX: DurableObjectNamespace }) {
const sandbox = getSandbox(env.SANDBOX, "repro");
const result = await sandbox.exec("echo hi");
return Response.json(result);
},
};
```

1. On WSL2 with a **6.18.x** kernel and native `docker-ce` (containerd image store), run the dev server (`@cloudflare/vite-plugin` `pnpm dev`, or `wrangler dev`).
2. `curl http://127.0.0.1:/`.
3. Request hangs, then `Container failed to start`. `docker ps` shows only the `...-proxy` sidecar, never the app container.

## Key evidence (failure is workerd/miniflare-side, not the image or Docker)

- **The built image runs fine standalone:** `docker run --rm cloudflare-dev/:` boots and the container-server listens on `:3000`.
- **Docker daemon logs (`journalctl -u docker`)** during a run show **only** the `-proxy` endpoint joining the bridge (recreated in a ~30s loop). There is **no create/start** for the app-image container — the create never reaches the daemon.
- Host→container **TCP and HTTP** on `:3000` = `200` in ~2ms; `docker0` (172.17.0.1) present and bindable. Networking to a manually-run container is fine.
- The only thing the app-container create does that a plain `docker run` and the proxy create do **not** is wire the container into the egress proxy's network — that step appears to be where it hangs.

## What was ruled out

- **Toolchain version** — reproduced on both `workerd 1.20260521.1` and the newest `workerd 1.20260701.1`.
- **The image / disk / BuildKit** — image builds (`docker build` rc=0) and runs standalone; isolated builds succeed.
- **`enableInternet`** — a `Sandbox extends Base { enableInternet = false }` subclass does **not** help; the `proxy-everything` sidecar is created for every local container regardless (see workers-sdk#14242).
- **Docker Desktop** — not in use; native `docker-ce`, active context `default`. A stale `desktop-linux` context was removed with no change.
- **BuildKit `only one connection allowed` session warnings** — temporally disjoint from the container-start attempts; not related.

## Hypothesis

An environment regression in the **local-dev container↔egress-proxy networking** path (miniflare/workerd) on **WSL2 kernel 6.18.x**. The container image, Docker, and host↔container networking all work in isolation; only workerd's app-container create (with proxy network wiring) fails. It is not fixed by upgrading the toolchain or by app-level config.

## Environment

| | |
|---|---|
| OS | WSL2 (Ubuntu), kernel **`6.18.33.2-microsoft-standard-WSL2`** (built 2026-06-18), WSL `2.7.10.0` |
| Docker | native **docker-ce 29.6.1** (not Docker Desktop); **containerd image store** (`overlayfs` / `io.containerd.snapshotter.v1`) |
| `@cloudflare/sandbox` | `0.12.3` (also `0.10.3`) |
| `@cloudflare/containers` | `0.3.7` (also `0.3.5`) |
| `@cloudflare/vite-plugin` | `1.43.0` (also `1.38.0`) |
| `wrangler` | `4.107.0` (also `4.94.0`) |
| `miniflare` | `4.20260701.0` (also `4.20260521.0`) |
| `workerd` | `1.20260701.1` (also `1.20260521.1`) |
| Node | `22.x` |

## Possibly related

- cloudflare/containers#155 — local-dev container monitor lifecycle / `cloudflare-dev/*` image-tagging race.
- cloudflare/workers-sdk#14242 — `proxy-everything` egress sidecar behavior in local dev.

Contributor guide

Open the contributing guide

Research direction

Reproduce with the wrangler.jsonc, Dockerfile, and src/index.ts example using wrangler dev or pnpm dev, then inspect the local-dev app-container creation and egress-proxy network-wiring path in miniflare/workerd. Done means the app container is created alongside the proxy sidecar and getSandbox(...).exec("echo hi") returns instead of timing out.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, linux, typescript
Domain
devtools, infrastructure, networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.