zed/docs/src/dev-containers.md
Toru Nayuki 26fc42721a
dev_container: Support the classic Docker builder via a setting (#59288)
Dev container image builds default to BuildKit (`docker buildx`).
Docker-compatible engines that lack an integrated BuildKit — notably
[Apple Container](https://github.com/apple/container) accessed through a
Docker-API bridge — cannot resolve a locally-built image in a `FROM`,
which breaks the dev container build: Zed builds the features image,
then a second `FROM <features-image>` build (the UID remap), and
BuildKit's docker-container/remote drivers can't see the daemon's local
image, failing with `pull access denied`.

The daemon's *classic* builder resolves locally-built images, and Zed
already generates a BuildKit-free Dockerfile for the non-BuildKit path
(multi-stage `FROM` + `COPY --from`, no `RUN --mount`). This wires that
path to a setting and makes the remaining build invocations actually use
the classic builder.

## Changes

- Add a `dev_container_use_buildkit` setting (tri-state):
- unset → auto-detect via the `docker buildx` plugin (current behavior)
  - `false` → force the classic builder
  - `true` → force BuildKit
- When the classic builder is selected, pass `DOCKER_BUILDKIT=0` (and
`COMPOSE_DOCKER_CLI_BUILD=0` for compose) to the feature-content build,
the compose build, and the UID-remap build, so multi-stage `FROM` of a
locally-built image resolves through the daemon's classic builder.
- Document the setting in `docs/src/dev-containers.md`.

With this setting plus a Docker-API bridge, a real Rails dev container
(compose: app + mysql + valkey, with features) builds and starts on
Apple Container.

## How to Review

- `settings_content.rs` / `dev_container/src/lib.rs` — the new setting
and its plumbing into `DevContainerContext`.
- `docker.rs` — `Docker::new` honors the setting
(`supports_compose_buildkit`), `docker_compose_build` selects the
classic builder; unit test
`use_buildkit_setting_overrides_buildx_detection`.
- `devcontainer_manifest.rs` — `DOCKER_BUILDKIT=0` for the
feature-content and UID-remap builds.

## Self-Review Checklist

- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- Added a `dev_container_use_buildkit` setting to build dev containers
with the classic Docker builder for engines without an integrated
BuildKit (e.g. Apple Container)
2026-06-15 07:04:03 +00:00

3.2 KiB

title description
Dev Containers - Zed Open projects in dev containers with Zed. Reproducible development environments using devcontainer.json configuration.

Dev Containers

Dev Containers provide a consistent, reproducible development environment by defining your project's dependencies, tools, and settings in a container configuration.

If your repository includes a .devcontainer/devcontainer.json file, Zed can open a project inside a development container.

Requirements

  • Docker or Podman must be installed and available in your PATH. If you use podman, you must set the use_podman setting in your Zed settings.json to true.
  • Your project must contain a .devcontainer/devcontainer.json directory/file.

By default Zed builds dev container images with BuildKit when the docker buildx plugin is available. If your Docker-compatible engine lacks an integrated BuildKit (for example, Apple Container accessed through a Docker-API bridge), set "dev_container_use_buildkit": false in your settings.json to use the classic Docker builder instead.

Using Dev Containers in Zed

Automatic prompt

When you open a project that contains the .devcontainer/devcontainer.json directory/file, Zed will display a prompt asking whether to open the project inside the dev container. Choosing "Open in Container" will:

  1. Build the dev container image (if needed).
  2. Launch the container.
  3. Reopen the project connected to the container environment.

Manual open

If you dismiss the prompt or want to reopen the project inside a container later, you can use Zed's command palette to run the "Project: Open Remote" command and select the option to open the project in a dev container. Alternatively, you can reach for the Remote Projects modal (through the {#kb projects::OpenRemote} binding) and choose the "Connect Dev Container" option.

Editing the dev container configuration

If you modify .devcontainer/devcontainer.json, Zed does not currently rebuild or reload the container automatically. After changing configuration:

  • Stop or kill the existing container manually (e.g., via docker kill <container>).
  • Reopen the project in the container.

Working in a Dev Container

Once connected, Zed operates inside the container environment for tasks, terminals, and language servers. Files are linked from your workspace into the container according to the dev container specification.

Extensions

You can specify extensions in .devcontainer/devcontainer.json under the "customizations" field like so:

{
  ...
  "customizations": {
    "zed": {
      "extensions": ["vue", "ruby"],
    },
    "vscode": {
      ...
    },
    "codespaces": {
      ...
    },
  }
}

Note that extensions load for the Zed session, so these extensions will exist on your local Zed instances as well.

Known Limitations

Note: This feature is still in development.

  • Configuration changes: Updates to devcontainer.json do not trigger automatic rebuilds or reloads; containers must be manually restarted.

See also

  • Remote Development for connecting to remote servers over SSH.
  • Tasks for running commands in the integrated terminal.