Commit Graph
17 Commits
Author SHA1 Message Date
Coinleft LFTandKirill Bulatov 1057c2cf3d Redact environment secrets from dev container docker exec logs (#63606)
# Objective

Fixes #63569

`run_docker_command` Debug-formatted the whole `docker exec` command, so
every `-e NAME=VALUE` pair forwarded into a dev container was written to
`Zed.log` in plaintext: once at DEBUG, and again in the error message
that `remote_client.rs` logs at ERROR on a failed reconnect.

## Solution

Render the command with `redact_arguments`, which replaces the value of
every `-e NAME=VALUE` argument with `<redacted>` before the arguments
are flattened, and pass the remaining arguments and stderr through
`util::redact::redact_command`.
Validate `containerEnv` and `remoteEnv` keys in `spawn_dev_container`
before any container is reused or built, because an empty key produced
`-e =VALUE`, which the Docker CLI rejects while echoing the value
verbatim to stderr.
Skip invalid names in `remote` as well, since `remote_env` is also
rehydrated from the workspace database.
The shared predicate lives in `util::redact::is_valid_environment_name`.

The DEBUG line now logs the redacted command and exit status only; the
previous stdout and stderr byte dumps are gone.

## Testing

`cargo test -p remote -p dev_container --lib`.
Unit tests cover redaction of forwarded env, argument boundaries,
assignments inside program arguments and stderr, invalid-name skipping
and rejection, and the podman CLI.

Release Notes:

- Fixed dev container environment variables being logged in full

---------

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
2026-09-04 03:02:13 +00:00
Rabindra Kumar Meher 864ff0ba3f Run string-form dev container lifecycle commands in /bin/sh -c (#60792)
# Objective

Fixes #60228.

String-form dev container lifecycle commands are currently executed by
splitting the command on spaces and running the first token directly.
This means shell features such as variable expansion, pipes,
redirection, and command chaining do not work.

According to the Dev Container specification, string-form lifecycle
commands should run through `/bin/sh -c`, while array-form commands
should continue to execute directly.

## Solution

- Added `LifecycleScript::shell_command()` to wrap string-form commands
in `/bin/sh -c`.
- Updated string deserialization to use `shell_command()` instead of
splitting on spaces.
- Kept array-form commands unchanged.

## Testing

- Ran `cargo test -p dev_container` (107 tests passed).
- Added a regression test to verify string-form commands run through
`/bin/sh -c`.
- Added a regression test to verify array-form commands still execute
directly.
- Updated the existing deserialization tests to match the expected
behavior.

## 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
- [x] Tests cover the new behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Fixed string-form dev container lifecycle commands so they execute
through `/bin/sh -c` as required by the Dev Container specification.
2026-07-31 08:53:21 +00:00
Alan P John b7de76402c dev_containers: Preserve Compose entrypoints by default (#61897)
# Objective

Docker Compose-based dev containers do not run their image or service
entrypoint when `overrideCommand` is omitted.

The Dev Container specification defaults `overrideCommand` to `true` for
image and Dockerfile configurations, but to `false` for Docker Compose
configurations. Zed treated an omitted value as `true` for every build
type and generated a Compose entrypoint override, preventing the
configured entrypoint from running.

Fixes #60456

## Solution

Resolve the effective value of `overrideCommand` based on the dev
container build type:

- Preserve the existing default of `true` for image and Dockerfile
configurations.
- Use the specification default of `false` for Docker Compose
configurations.
- Continue to give an explicitly configured `overrideCommand` precedence
over the default.

Use the resolved value when deciding whether to generate Zed's
entrypoint script.

Add regression tests covering the defaults for image, Dockerfile, and
Docker Compose configurations, along with explicit overrides in both
directions.

## Testing

Automated testing:

- `cargo fmt --check`
- `cargo test -p dev_container override_command --lib`
- `./script/clippy -p dev_container --lib`
- `cargo build -p zed`

All three focused tests pass, and Clippy passes with warnings denied.

Manually tested on Linux using the Docker Compose reproduction from
#60456:

1. Built an Alpine image with an `ENTRYPOINT` that writes
`/tmp/entrypoint-marker.log`.
2. Configured the Compose service with `command: sleep infinity`.
3. Omitted `overrideCommand` from `devcontainer.json`.
4. Opened the project in the current stable release and confirmed that
the marker file was not created.
5. Opened a fresh container using this branch's development build and
confirmed that:
   - `/tmp/entrypoint-marker.log` was created.
   - The Compose `sleep infinity` command remained active.

Testing was performed with Docker Compose on Linux. I did not manually
test this change on macOS or Windows, but the default resolution is
platform-independent.

## 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

## Showcase

### Before

Current stable Zed replaces the Compose entrypoint when
`overrideCommand` is omitted, so `/tmp/entrypoint-marker.log` is not
created.

Zed 1.12.0

<img width="2827" height="1709" alt="image"
src="https://github.com/user-attachments/assets/04dadd66-5e95-4ea8-8183-6156793f0654"
/>

### After

The development build preserves the Compose entrypoint by default. The
marker file is created and the Compose service command remains active.

<img width="2827" height="1709" alt="image"
src="https://github.com/user-attachments/assets/cdd9808b-7867-42d8-bec7-97af9c170b0a"
/>


---

Release Notes:

- Fixed Docker Compose dev containers not running their configured
entrypoints by default.
2026-07-31 06:39:51 +00:00
Duncan Ogilvie 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.
2026-07-21 14:15:32 +00:00
Yauhen 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`.
2026-05-29 05:12:28 +00:00
KyleBarton 518502e5ef Respect override command in devcontainer (#57204)
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 #56357

Release Notes:

- Fixed bug where devcontainers were not respecting override_command
2026-05-28 11:22:41 +00:00
Ivan Mironov 66a77d29fd Fix devcontainer localEnv/containerEnv substitution when variable is undefined (#53728)
Existing code replaces only the variables that are present in the
environment. It ignores references to undefined variables and leaves
them as is.

Consider following devcontainer.json:

```json
{
  ...
  "remoteEnv": {
    "RUSTFLAGS": "${localEnv:RUSTFLAGS}"
  },
  ...
}
```

Existing code will set RUSTFLAGS inside the dev container to a correct
value only if RUSTFLAGS is defined outside the dev container. If
RUSTFLAGS is not defined outside, Zed will erroneously set RUSTFLAGS to
`${localEnv:RUSTFLAGS}`.

This patch fixes this by replacing such references with either empty
strings or provided default values (`${localEnv:VARNAME:default}`).

This patch also removes replacement of `\` with `/` for environment
variables. Existing code makes no sense as simple replacement will not
magically make Windows paths valid on *nix. It is also guaranteed to
break things: think about passing passwords via env vars, for example.

I also noticed that, for some reason, existing code serializes k-v maps
to JSON, then tries to replace the references, and after that
deserializes modified JSON back. I believe that this is horribly wrong
and may have some security implications. This is out of the scope of
this patch. And I hope that somebody from the Zed team will provide the
reasoning behind this code.

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 #ISSUE~~ This pull request is also a bug report.

Release Notes:

- Fixed substitution of `${localEnv:VARNAME}` and
`${containerEnv:VARNAME}` in devcontainer.json when variable is not
defined
2026-04-20 16:12:17 -04:00
Kunall Banerjee cd12d5f98d dev_container: Make all PortAttributes fields optional (#53799)
The Dev Container [metadata
reference](https://containers.dev/implementors/json_reference/#port-attributes)
defines all five `PortAttributes` fields (`elevateIfNeeded`, `label`,
`onAutoForward`, `protocol`, `requireLocalPort`) as optional with
defined defaults. The struct required all of them, causing
deserialization failures for any `portsAttributes` entry that omitted a
field.

Add `#[serde(default)]` to each field, wrap `label` and `protocol` in
`Option<T>` (spec default: not set), and derive `Default` on
`OnAutoForward` with `Notify` as the default variant (spec default:
`notify`). The bool fields already default to false via
`serde(default)`, matching the spec.

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
- [ ] Performance impact has been considered and is acceptable

Closes #53686.

Release Notes:

- Made all `PortAttributes` fields optional according to the Dev
Container spec
2026-04-20 10:05:12 -07:00
KyleBarton 17026b10d6 Use dockerfile build args correctly, respect context path, fix image aliasing (#54210)
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 #54193

Additionally, respects `cacheFrom` and `options` args defined in
devcontainer.json's `build` object. Also, addresses a bug which was
hiding these problems by overriding the primary build target with
aliasing.

Release Notes:

- Fixed an image aliasing but, respect build context and build args in
dev containers
2026-04-20 08:38:53 -07:00
KyleBarton 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
2026-04-16 11:50:08 -07:00
KyleBarton c2736df3c7 Respect runArgs for dev containers (#53931)
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 #53503

Release Notes:

- Fixed gap where runArgs were not respected when specified in
devcontainer.json
2026-04-15 08:24:34 -07:00
KyleBarton 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
2026-04-09 13:27:29 -07:00
KyleBarton 358a796a94 Appropriately deserialize app_port in devcontainer.json (#53322)
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 #53263

Properly deserializes the app_port field, even if it is an array of
strings. Also, removes app_port from consideration when building a
docker-compose-based dev container, since the spec specifies that it
only applies to non-docker-compose dev containers.

Release Notes:

- Fixed app_port deserialization in dev container
2026-04-07 10:58:35 -07:00
Peter SiegelandKyleBarton 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>
2026-04-06 11:46:54 -07:00
KyleBarton 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
2026-04-06 09:01:51 -07:00
KyleBarton e9b280afe0 Account for windows absolute paths in bind mounts (#53093)
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

Addresses an auxiliary windows bug found in #52924 - bind mounts are not
working in Windows because MountDefinition is not accounting for
absolute Windows paths.

Release Notes:

- Fixed windows bind mount issue with dev containers
2026-04-03 14:55:12 -07:00
KyleBarton 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
2026-04-01 08:16:27 -07:00