01acd0ee8e906dd0ec8b526fe08da94444a5e2af
17
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6aed696155 |
Fix Devcontainer bugs/spec mismatches (#59020)
When testing Zed on our team's Devcontainer I found some missing features/bugs/spec mismatches. Commit messages were written by hand, code reviewed and tested manually, but everything was written by Claude/Codex based on: - https://github.com/devcontainers/cli - https://github.com/devcontainers/spec The main use case of the metadata is that you can `devcontainer exec` and `devcontainer up` into a container Zed started (and vice versa). The same with VSCode, it will reuse Zed's created devcontainer correctly now. This is useful when using LLMs so they can run commands in the same devcontainer you have open. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Fixed Dev Container compatibility and lifecycle behavior. |
||
|
|
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) |
||
|
|
d3070bbc0d |
dev_container: Respect runServices for Docker Compose (#56293)
This PR fixes Docker Compose dev containers starting every service in
the compose project, even when `devcontainer.json` specifies
`runServices`.
Previously, Zed deserialized `runServices` but did not use it when
invoking Docker Compose. The startup command was:
```sh
docker compose ... up -d
```
With no service operands, Compose starts every enabled service in the
project. This means unrelated services are started even when the
devcontainer config asks to run only the primary service and its
dependencies.
The fix propagates `runServices` into the Docker Compose build/start
path so Zed invokes Compose with the requested services:
```sh
docker compose ... up -d devcontainer
```
Compose will still start services required by `depends_on`, but
unrelated services are left untouched.
**Reproduction**
`.devcontainer/devcontainer.json`:
```json
{
"name": "Run Services",
"dockerComposeFile": "../compose.yml",
"service": "devcontainer",
"runServices": ["devcontainer"],
"workspaceFolder": "/workspace"
}
```
`compose.yml`:
```yaml
services:
devcontainer:
image: ubuntu:24.04
command: sleep infinity
volumes:
- .:/workspace
depends_on:
- database
database:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: postgres
unrelated:
image: nginx:alpine
```
**Expected**: Zed starts `devcontainer` and `database`.
**Before this fix**: Zed also starts `unrelated`.
**After this fix**: `unrelated` remains stopped.
Closes: https://github.com/zed-industries/zed/issues/57279
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] 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:
- Fixed Docker Compose dev containers starting services not listed in
`runServices`.
|
||
|
|
707c00b474 |
Support local devcontainer features (#55225)
Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] 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 Closes #53486 Note that this builds off of #55117 because both touched similar code areas; I thought it best to in order to avoid conflicts. Release Notes: - Added support for local features in dev containers |
||
|
|
f939ec6049 |
dev_container: Align compose project name with reference CLI (#54302)
> **Draft / open question for maintainers.** The failure mode this fixes is narrow — a new-Zed-created container exists under the `name`-field project while a CLI-derivation tool (`@devcontainers/cli`, VS Code) operates on the same folder (the container persists in Docker, so the originating Zed session doesn't need to still be open). See issue #54255 failure mode 3 and the fixture's step 6. > > I'd like to pose this as a question rather than a claim: is matching `@devcontainers/cli`'s `getProjectName` precedence something the project wants to take on, given the narrowness of the bug? I wrote this implementation mostly as a way to explore what parity would actually cost — happy to close it if you'd rather leave it as-is, or pare it down (e.g. just rule 4) if a partial match is preferable. > > The broader value beyond this specific bug: devcontainer impls agreeing on the same project name means containers created by Zed, the devcontainer CLI, and VS Code are interchangeable for the same folder, which feels worth it to me — but you know the project's priorities better. > > Folds in #54068 (detection) — closing that PR unmerged; its `MultipleMatchingContainers` error lands here. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] 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 Closes #54255 ## Summary **Match `@devcontainers/cli`'s full `getProjectName` precedence.** Replaces `safe_id_lower(devcontainer.json's name)` with the five-step chain the reference CLI walks (see [`src/spec-node/dockerCompose.ts` in devcontainers/cli](https://github.com/devcontainers/cli/blob/main/src/spec-node/dockerCompose.ts)): 1. `COMPOSE_PROJECT_NAME` from the local environment. 2. `COMPOSE_PROJECT_NAME=` in the workspace `.env` file. 3. Top-level `name:` on the merged compose config, when at least one fragment declared it explicitly. 4. `${workspaceFolderBasename}_devcontainer` — only when the first compose file's directory is `<workspace>/.devcontainer/`. 5. Otherwise, the plain basename of the first compose file's directory (no suffix). The old Zed implementation diverged at every one of those inputs: any user setting `COMPOSE_PROJECT_NAME`, shipping a `.env` with one, declaring a top-level compose `name:`, or pointing `dockerComposeFile` outside `.devcontainer/` (e.g. `"../docker-compose.yml"`) got a different project namespace than the CLI and VS Code, producing two compose projects for the same folder. Adds a small `sanitize_compose_project_name()` helper implementing the CLI's rules (lowercase + strip `[^-_a-z0-9]`) — notably preserving hyphens, which `safe_id_lower` would have replaced with underscores. Adds two helpers used by the precedence walk: - `parse_dotenv_compose_project_name` — line scan extracting `COMPOSE_PROJECT_NAME=…` from the workspace `.env`, matching the subset the CLI's regex dotenv reader recognizes. - `compose_fragment_declares_name` — parses each compose fragment with `yaml-rust2` (already a transitive workspace dep; slated to become a direct dep via #53922) and checks for a `name` key on the root mapping (block, quoted, or flow style all work), matching the CLI's own `yaml.load`. `docker compose config` always injects `name: devcontainer` into its merged output when no fragment declared one, so rule 3 needs to distinguish the user-provided case from the injected default — this helper supplies that signal. On YAML parse failure it returns "not declared" (rule 4 applies), matching the CLI's fallback. `project_name()` becomes async and fallible (`async fn project_name(&self) -> Result<String, DevContainerError>`) so it can load the `.env` file and each compose fragment via `self.fs.load`. Four call sites now `.await?` the derivation. Real I/O errors on the `.env` read propagate as `FilesystemError` (matching the CLI's narrow `ENOENT`/`EISDIR` swallow); fragment-rescan read errors are logged and skipped (matching the CLI's broader try/catch over its fragment read + parse). The `name` field is still used as the features image-tag prefix (`generate_features_image_tag`); only the compose project namespace is decoupled from it. **Duplicate-container detection (from #54068).** When `check_for_existing_container`'s label-based lookup returns more than one match, propagate `MultipleMatchingContainers(ids)` with instructions to clean up the stale one(s). This covers the mixed-version upgrade edge case where a pre-fix Zed left a container under the legacy project name alongside a CLI-style one — transparent to users in the common case (one tool, one container), explicit error when two legacy siblings need manual cleanup. ## Why Full write-up with verified fixtures and captured output: #54255. Three failure modes from the same root cause, all resolved by this change: 1. **Interop** — opening a folder in both Zed and `devcontainer up` (or Zed and VS Code) creates two compose projects with identical `devcontainer.local_folder` + `devcontainer.config_file` labels, breaking the spec's uniqueness invariant. 2. **Cross-worktree silent db/volume reuse** — if multiple git worktrees share a `devcontainer.json` with the same `name`, Zed uses the same compose project for all of them; Compose reuses stateful siblings (db, cache, localstack) by config-hash, so worktree B silently inherits worktree A's database. Fixture + captured output: [antont/zed-devcontainer-db-share-repro](https://github.com/antont/zed-devcontainer-db-share-repro). 3. **Mixed-version Zed sessions** — the Rust impl landed in stable v0.232.2 (2026-04-15, #52338). Older Zed (≤v0.231.x) shelled out to `@devcontainers/cli` so it used the reference derivation. The collision shows up when a new-Zed-created container exists under the name-field project while a CLI-derivation tool (old Zed, `devcontainer up`, VS Code) operates on the same folder. ## Migration / compatibility Existing Zed-created containers (under the old `safe_id_lower(name)` project) continue to be found via `check_for_existing_container`'s label-based lookup — they're looked up by `devcontainer.local_folder` + `devcontainer.config_file`, not by project name. A user with duplicate legacy containers from a prior Zed session sees `MultipleMatchingContainers` with cleanup instructions. ## Revision — 2026-04-22 Revised per @KyleBarton review on the prior version: - Swapped the YAML parser from `serde_yaml_ng` to `yaml-rust2` (already transitive via `tree-sitter-yaml`; net reduction of one direct workspace dep; also what #53922 will pull in). - Dropped the mixed-version tiebreak (`pick_canonical_container`) and its `com.docker.compose.project` serde label. The edge case it covered is transient enough to address via the explicit `MultipleMatchingContainers` error rather than permanent tiebreaking code. - Folded #54068's detection commit into this PR; #54068 closed unmerged. - Rebased onto `main`. ## Test plan - [x] `cargo test -p dev_container --lib` — 89 passed, including: - `sanitize_compose_project_name_matches_cli_rules` - `--project-name` assertion added to `test_spawns_devcontainer_with_docker_compose` - `check_for_existing_container_errors_when_multiple_match` - `derive_project_name_env_wins_over_everything` - `derive_project_name_dotenv_wins_over_compose_and_fallback` - `derive_project_name_compose_name_wins_over_fallback` - `derive_project_name_skips_compose_name_when_not_explicitly_declared` - `derive_project_name_omits_suffix_when_compose_file_outside_devcontainer_dir` - `derive_project_name_normalizes_compose_path_for_rule_4` - `compose_fragment_declares_name_detects_top_level_name_key` (covers block, quoted-key, and flow-style roots, plus parse failure → not-declared) - `is_missing_file_error_only_accepts_notfound_and_isadirectory` - [x] `cargo fmt --all` — clean - [x] `./script/clippy -p dev_container` — clean - [x] **End-to-end with fixture** [antont/zed-devcontainer-compose-test](https://github.com/antont/zed-devcontainer-compose-test): - Build `zed` from this branch. - Clean slate: `docker ps -a --filter "label=devcontainer.local_folder=$PWD" -q | xargs -r docker rm -f` - `zed --dev-container /path/to/devcontainer-compose-test` → Zed creates container under project `devcontainer-compose-test_devcontainer` (was `compose_duplicate_repro` before the fix). - `devcontainer up --workspace-folder $PWD` → CLI reports the same `containerId` Zed created; no second compose project is introduced. - Captured: `devcontainer-compose-test_devcontainer-app-1`, `composeProjectName: "devcontainer-compose-test_devcontainer"` reported by both tools. Release Notes: - Fixed dev container Docker Compose project name now matches the full `getProjectName` precedence from the reference devcontainer CLI (`COMPOSE_PROJECT_NAME` in the environment, then in the workspace `.env`, then an explicit top-level `name:` on the merged compose config, then the basename of the first compose file's directory — with the `_devcontainer` suffix only when that directory is `<workspace>/.devcontainer`). This prevents duplicate containers when the same folder is opened with both Zed and the devcontainer CLI / VS Code. --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
54f544430d |
dev_container: Fix environment variables without an equals sign were treated as fatal parsing errors. (#53864)
in vscode the environment variables without an equals sign are ignored https://github.com/devcontainers/cli/blob/main/src/spec-node/utils.ts#L488-L498 Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] 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 Closes #53470 Release Notes: - Fix environment variables without an equals sign were treated as fatal parsing errors. |
||
|
|
5e6e41155e |
Simplify remote workspace folder calculation for Dev Containers (#53829)
Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] 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 Closes #53635 Release Notes: - Fixed issues with Windows pathing when calculating target workspace directory for dev containers |
||
|
|
75fa566511 |
dev_container: Detect actual buildx availability instead of assuming Docker has it (#53910)
`supports_compose_buildkit()` returned `!self.is_podman()`, assuming every Docker install has buildx. On setups like Colima where the buildx CLI plugin isn't installed, this causes builds to fail with "classic builder doesn't support additional contexts" since `DOCKER_BUILDKIT=1` alone isn't enough without the plugin. Now probes for `docker buildx version` at construction time and caches the result. When buildx isn't found, the existing scratch-image fallback path (same one Podman uses) kicks in instead. Closes #53890 Release Notes: - Fixed dev container builds failing on Docker installations without the buildx plugin. --------- Co-authored-by: krisswee <krisswee@users.noreply.github.com> Co-authored-by: KyleBarton <kjb@initialcapacity.io> |
||
|
|
2d3f49e4b2 |
dev_container: Handle devcontainer.metadata label as JSON object or array (#53557)
Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] 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 ## Details - The [devcontainer CLI writes the `devcontainer.metadata` label as a bare JSON object](https://github.com/devcontainers/cli/issues/1054) when there is only one metadata entry (e.g. docker-compose devcontainer with a Dockerfile and no features) - Zed's `deserialize_metadata` only accepted a JSON array, causing deserialization to fail with `invalid type: map, expected a sequence` - This made it impossible to attach to existing docker-compose devcontainers created by the devcontainer CLI or VS Code The fix tries parsing as an array first, then falls back to parsing as a single object wrapped in a vec. This mirrors how the [devcontainer CLI itself reads the label](https://github.com/devcontainers/cli/blob/main/src/spec-node/imageMetadata.ts#L476-L493). An upstream fix has also been submitted: https://github.com/devcontainers/cli/pull/1199 ## Reproduction 1. Create a docker-compose devcontainer with a Dockerfile and no features: `.devcontainer/devcontainer.json`: ```json { "name": "repro", "dockerComposeFile": "docker-compose.yml", "service": "app", "remoteUser": "root" } ``` `.devcontainer/docker-compose.yml`: ```yaml services: app: build: context: . dockerfile: Dockerfile command: sleep infinity volumes: - ..:/workspace ``` `.devcontainer/Dockerfile`: ```dockerfile FROM ubuntu:24.04 ``` 2. `devcontainer up --workspace-folder .` 3. Open the folder in Zed, fails with metadata deserialization error Release Notes: - Fixed attaching to a devcontainer that has a single metadata element which was started with `devcontainer-cli` |
||
|
|
b8766ef3af |
Use -- in more places that call subcommands with paths (#53484)
Thanks to Dario Weißer for the suggestion Release Notes: - Fixed some potential edge cases when paths in a project started with `-`. |
||
|
|
bd50418150 |
Fix dockerfile image and alias parsing (#53538)
Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] 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 Closes #52928 Release Notes: - Fixed handling of multi-stage and stage-specified dockerfiles in dev container manifests - Fixed the way we find the base image in a dev container when build args need expansion |
||
|
|
909f6d12fc |
dev_container: Make volumes key and source key in volume mounts optional (#53137)
Fixes some issues concerning volume mounts in the `dev_container` integration: 1. Docker Compose services that don't define a volumes key cause deserialization to fail because the field was required. This field is not strictly necessary, i.e. for other services in a docker compose devcontainer configuration which the editor is not attached to. 1. Volume mounts where source or target is absent (e.g. `tmpfs` mounts that only need a target) also fail to parse because both fields were required. This makes the source key optional, matching the Docker Compose spec. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] 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: - Fixed devcontainer initialization erroneously requiring each service to have a volumes key. - Fixed devcontainer initialization erroneously requiring source keys for all volume mounts. --------- Co-authored-by: KyleBarton <kjb@initialcapacity.io> |
||
|
|
4b1e0a30b8 |
dev_container: Parse env vars and docker labels with = in values correctly (#53134)
Fixes a parsing issue where docker env var key/value pairs can contain an "=" character in the value. This is pretty common and present in all [nvidia/cuda](https://hub.docker.com/r/nvidia/cuda) docker images. Also adds some tests for env var parsing. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] 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: - Fixed a parsing failure where docker env var key/value pairs can contain an "=" character in the value. |
||
|
|
c9d799e5e6 |
Ensure updateUID gets run for docker-compose and plain images (#53106)
Dev Containers should run a script which updates the remote UID of the image user, so that files are still accessible. This was being run incorrectly (on the Docker-compose side) or not at all (in the case of a plain dev container image). This change fixes this Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] 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 Closes #53081 Release Notes: - Fixed dev container behavior for configs which use images without a dockerfile |
||
|
|
5edb40c7a8 |
Use an object for docker compose ports rather than raw string (#53090)
Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] 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 Closes #53048 Release Notes: - Fixed serialization error with Docker Compose for dev containers |
||
|
|
bde6a01068 |
Fix/devcontainer compose labels (#53057)
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 Closes #53042 Release Notes: - Fixed dev container failing to open when Docker Compose file contains `labels` --------- Co-authored-by: KyleBarton <kjb@initialcapacity.io> |
||
|
|
3eadd41b5d |
Dev containers native implementation (#52338)
## Context Closes #11473 In-house Zed implementation of devcontainers. Replaces the dependency on the [reference implementation](https://github.com/devcontainers/cli) via Node. This enables additional features with this implementation: 1. Zed extensions can be specified in the `customizations` block, via this syntax in `devcontainer.json: ``` ... "customizations": { "zed": { "extensions": ["vue", "ruby"], }, }, ``` 2. [forwardPorts](https://containers.dev/implementors/json_reference/#general-properties) are supported for multiple ports proxied to the host ## How to Review <!-- Help reviewers focus their attention: - For small PRs: note what to focus on (e.g., "error handling in foo.rs") - For large PRs (>400 LOC): provide a guided tour — numbered list of files/commits to read in order. (The `large-pr` label is applied automatically.) - See the review process guidelines for comment conventions --> ## Self-Review Checklist <!-- Check before requesting review: --> - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] 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: - Improved devcontainer implementation by moving initialization and creation in-house |