From 482e5f9e022c82f0f12e776f196df81a440eae03 Mon Sep 17 00:00:00 2001
From: Mason Malone <651224+MasonM@users.noreply.github.com>
Date: Mon, 6 Jan 2025 06:32:40 -0500
Subject: [PATCH 01/13] fix: remove inapplicable line for `dockerComposeFile`
(#535)
The "array syntax will execute the command without a shell" line isn't applicable to `dockerComposeFile`, since it isn't specifying a command to be executed. I'm guessing this was a copy-and-paste mistake.
---
docs/specs/devcontainerjson-reference.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/specs/devcontainerjson-reference.md b/docs/specs/devcontainerjson-reference.md
index be39c012..a479b5eb 100644
--- a/docs/specs/devcontainerjson-reference.md
+++ b/docs/specs/devcontainerjson-reference.md
@@ -53,7 +53,7 @@ The focus of `devcontainer.json` is to describe how to enrich a container for th
| Property | Type | Description |
|----------|------|-------------|
-| `dockerComposeFile` | string,
array | **Required** when [using Docker Compose](https://docs.docker.com/compose/). Path or an ordered list of paths to Docker Compose files relative to the `devcontainer.json` file. Using an array is useful [when extending your Docker Compose configuration](https://docs.docker.com/compose/extends/#multiple-compose-files). The order of the array matters since the contents of later files can override values set in previous ones.
The default `.env` file is picked up from the root of the project, but you can use `env_file` in your Docker Compose file to specify an alternate location.
Note that the array syntax will execute the command without a shell. You can [learn more](#formatting-string-vs-array-properties) about formatting string vs array properties. |
+| `dockerComposeFile` | string,
array | **Required** when [using Docker Compose](https://docs.docker.com/compose/). Path or an ordered list of paths to Docker Compose files relative to the `devcontainer.json` file. Using an array is useful [when extending your Docker Compose configuration](https://docs.docker.com/compose/extends/#multiple-compose-files). The order of the array matters since the contents of later files can override values set in previous ones.
The default `.env` file is picked up from the root of the project, but you can use `env_file` in your Docker Compose file to specify an alternate location. |
| `service` | string | **Required** when [using Docker Compose](https://docs.docker.com/compose/). The name of the service `devcontainer.json` supporting services / tools should connect to once running. |
| `runServices` | array | An array of services in your Docker Compose configuration that should be started by `devcontainer.json` supporting services / tools. These will also be stopped when you disconnect unless `"shutdownAction"` is `"none"`. Defaults to all services. |
| `workspaceFolder` | string | Sets the default path that `devcontainer.json` supporting services / tools should open when connecting to the container (which is often the path to a volume mount where the source code can be found in the container). Defaults to `"/"`. |
From 9097eec413cacbe1c6aafad213e965af83c2bb7b Mon Sep 17 00:00:00 2001
From: Julius F
Date: Thu, 17 Apr 2025 17:20:21 +0200
Subject: [PATCH 02/13] doc: fix invalid json feature-dependencies.md
There was a colon missing in the last dependsOn
---
docs/specs/feature-dependencies.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/specs/feature-dependencies.md b/docs/specs/feature-dependencies.md
index 97d4f12c..60601ad2 100644
--- a/docs/specs/feature-dependencies.md
+++ b/docs/specs/feature-dependencies.md
@@ -59,7 +59,7 @@ An example `devcontainer-feature.json` file with a dependency on four other publ
},
"features.azurecr.io/third:1": {},
"features.azurecr.io/fourth:1.2.3": {},
- "features.azurecr.io/fifth@sha256:a4cdc44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" {},
+ "features.azurecr.io/fifth@sha256:a4cdc44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855": {}
}
}
```
@@ -237,4 +237,4 @@ Features should be authored with the following considerations:
Dependency resolution is only performed on initial container creation by reading the `features` object of `devcontainer.json` and resolving the Features in that point in time. For subsequent creations from an image (or resumes of a dev container), the dependency tree is **not** re-calculated. To re-calculate the dependency tree, the user must delete the image (or dev container) and recreate it from a `devcontainer.json`.
-Once Feature dependencies are resolved, they are treated the same as if members of the user-defined Features. That means both user-defined Features and their dependencies are stored in the image's metadata.
\ No newline at end of file
+Once Feature dependencies are resolved, they are treated the same as if members of the user-defined Features. That means both user-defined Features and their dependencies are stored in the image's metadata.
From c600c4ff8a2d8d2ec71c3da7fde87156e17c3a0a Mon Sep 17 00:00:00 2001
From: Hossein Abbasi <16090309+hsnabszhdn@users.noreply.github.com>
Date: Fri, 4 Jul 2025 11:28:37 +1000
Subject: [PATCH 03/13] Apply consistent use of 'e.g.' and 'i.e.'
---
docs/specs/declarative-secrets.md | 2 +-
.../devcontainer-features-distribution.md | 4 +--
docs/specs/devcontainer-features.md | 26 +++++++++----------
docs/specs/devcontainer-id-variable.md | 4 +--
docs/specs/devcontainer-reference.md | 6 ++---
.../devcontainer-templates-distribution.md | 2 +-
docs/specs/devcontainer-templates.md | 4 +--
docs/specs/devcontainerjson-reference.md | 2 +-
docs/specs/feature-dependencies.md | 12 ++++-----
...eatures-legacyIds-deprecated-properties.md | 2 +-
docs/specs/secrets-support.md | 2 +-
11 files changed, 33 insertions(+), 33 deletions(-)
diff --git a/docs/specs/declarative-secrets.md b/docs/specs/declarative-secrets.md
index 372574a6..ba3cfd55 100644
--- a/docs/specs/declarative-secrets.md
+++ b/docs/specs/declarative-secrets.md
@@ -14,7 +14,7 @@ Various projects exist in the wild that require various secrets for them to run
- https://github.com/openai/openai-quickstart-python
- https://github.com/openai/openai-quickstart-node
-Today these projects have to include specific instructions e.g. in their README telling users where to procure what they need to run and then how to set it up as a secret or add it as an environment variable. This currently acts as an impediment to adoption and promotion of dev containers for these projects.
+Today these projects have to include specific instructions (e.g. in their README) telling users where to procure what they need to run and then how to set it up as a secret or add it as an environment variable. This currently acts as an impediment to adoption and promotion of dev containers for these projects.
## Goal
diff --git a/docs/specs/devcontainer-features-distribution.md b/docs/specs/devcontainer-features-distribution.md
index e2c09615..8c0a2d3a 100644
--- a/docs/specs/devcontainer-features-distribution.md
+++ b/docs/specs/devcontainer-features-distribution.md
@@ -117,7 +117,7 @@ done
```
-The "namespace" is the globally identifiable name for the collection of Features. (eg: `owner/repo` for the source code's git repository).
+The "namespace" is the globally identifiable name for the collection of Features (e.g. `owner/repo` for the source code's git repository).
The auto-generated `devcontainer-collection.json` is pushed to the registry with the same `namespace` as above and no accompanying `feature` name. The collection file is always tagged as `latest`.
@@ -184,7 +184,7 @@ Additional constraints exists when including local Features in a project:
* The local Feature's sub-folder **must** contain at least a `devcontainer-feature.json` file and `install.sh` entrypoint script, mirroring the [previously outlined file structure](#Source-code).
-The relative path is provided using unix-style path syntax (eg `./myFeature`) regardless of the host operating system.
+The relative path is provided using unix-style path syntax (e.g. `./myFeature`) regardless of the host operating system.
An example project is illustrated below:
diff --git a/docs/specs/devcontainer-features.md b/docs/specs/devcontainer-features.md
index 844575a8..c14297b8 100644
--- a/docs/specs/devcontainer-features.md
+++ b/docs/specs/devcontainer-features.md
@@ -30,7 +30,7 @@ All properties are optional **except for `id`, `version`, and `name`**.
| Property | Type | Description |
| :--- | :--- | :--- |
| `id` | string | **Required**: Identifier of the Feature. Must be unique in the context of the repository where the Feature exists and must match the name of the directory where the `devcontainer-feature.json` resides. ID should be provided lowercase. |
-| `version` | string | **Required**: The semantic version of the Feature (e.g: `1.0.0`). |
+| `version` | string | **Required**: The semantic version of the Feature (e.g. `1.0.0`). |
| `name` | string | **Required**: A "human-friendly" display name for the Feature. |
| `description` | string | Description of the Feature. |
| `documentationURL` | string | Url that points to the documentation of the Feature. |
@@ -50,7 +50,7 @@ All properties are optional **except for `id`, `version`, and `name`**.
| `deprecated` | boolean | Indicates that the Feature is deprecated, and will not receive any further updates/support. This property is intended to be used by the supporting tools for highlighting Feature deprecation. |
| `mounts` | object | Defaults to unset. Cross-orchestrator way to add additional mounts to a container. Each value is an object that accepts the same values as the [Docker CLI `--mount` flag](https://docs.docker.com/engine/reference/commandline/run/#mount). The Pre-defined [devcontainerId](./devcontainerjson-reference.md/#variables-in-devcontainerjson) variable may be referenced in the value. For example:
`"mounts": [{ "source": "dind-var-lib-docker", "target": "/var/lib/docker", "type": "volume" }]` |
-(**) The ID must refer to either a Feature (1) published to an OCI registry, (2) a Feature Tgz URI, or (3) a Feature in the local file tree. Deprecated Feature identifiers (i.e GitHub Release) are not supported and the presence of this property may be considered a fatal error or ignored. For [local Features (ie: during development)](https://containers.dev/implementors/features-distribution/#addendum-locally-referenced), you may also depend on other local Features by providing a relative path to the Feature, relative to folder containing the active `devcontainer.json`. This behavior of Features within this property again mirror the `features` object in `devcontainer.json`.
+(**) The ID must refer to either a Feature (1) published to an OCI registry, (2) a Feature Tgz URI, or (3) a Feature in the local file tree. Deprecated Feature identifiers (i.e. GitHub Release) are not supported and the presence of this property may be considered a fatal error or ignored. For [local Features (i.e. during development)](https://containers.dev/implementors/features-distribution/#addendum-locally-referenced), you may also depend on other local Features by providing a relative path to the Feature, relative to folder containing the active `devcontainer.json`. This behavior of Features within this property again mirror the `features` object in `devcontainer.json`.
### Lifecycle Hooks
@@ -68,7 +68,7 @@ The following lifecycle hooks may be declared as properties of `devcontainer-fea
Each property mirrors the behavior of the matching property in [`devcontainer.json`](/docs/specs/devcontainerjson-reference.md#Lifecycle-scripts), including the behavior that commands are executed from the context of the [project workspace folder](https://containers.dev/implementors/spec/#project-workspace-folder).
-For each lifecycle hook (in [Feature installation order](https://containers.dev/implementors/features/#installation-order)), each command contributed by a Feature is executed in sequence (blocking the next command from executing). Commands provided by Features are always executed _before_ any user-provided lifecycle commands (i.e: in the `devcontainer.json`).
+For each lifecycle hook (in [Feature installation order](https://containers.dev/implementors/features/#installation-order)), each command contributed by a Feature is executed in sequence (blocking the next command from executing). Commands provided by Features are always executed _before_ any user-provided lifecycle commands (i.e. in the `devcontainer.json`).
If a Feature provides a given command with the [object syntax](/docs/specs/devcontainerjson-reference.md#formatting-string-vs-array-properties), all commands within that group are executed in parallel, but still blocking commands from subsequent Features and/or the `devcontainer.json`.
@@ -120,9 +120,9 @@ Implementations can choose how to compute this identifier. They must ensure that
The following assumes that a dev container can be identified among other dev containers on the same Docker host by a set of labels on the container. Implementations may choose to follow this approach.
-The identifier is derived from the set of container labels uniquely identifying the dev container. It is up to the implementation to choose these labels. E.g., if the dev container is based on a local folder the label could be named `devcontainer.local_folder` and have the local folder's path as its value.
+The identifier is derived from the set of container labels uniquely identifying the dev container. It is up to the implementation to choose these labels. For example, if the dev container is based on a local folder, the label could be named `devcontainer.local_folder` and have the local folder's path as its value.
-E.g., the [`ghcr.io/devcontainers/features/docker-in-docker` Feature](https://github.com/devcontainers/features/blob/main/src/docker-in-docker/devcontainer-feature.json) could use the dev container id with:
+For example, the [`ghcr.io/devcontainers/features/docker-in-docker` Feature](https://github.com/devcontainers/features/blob/main/src/docker-in-docker/devcontainer-feature.json) could use the dev container id with:
```jsonc
{
@@ -249,13 +249,13 @@ _For information on distributing Features, see [devcontainer-features-distributi
### Invoking `install.sh`
-The `install.sh` script for each Feature should be executed as `root` during a container image build. This allows the script to add needed OS dependencies or settings that could not otherwise be modified. This also allows the script to switch into another user's context using the `su` command (e.g., `su ${USERNAME} -c "command-goes-here"`). In combination, this allows both root and non-root image modifications to occur even if `sudo` is not present in the base image for security reasons.
+The `install.sh` script for each Feature should be executed as `root` during a container image build. This allows the script to add needed OS dependencies or settings that could not otherwise be modified. This also allows the script to switch into another user's context using the `su` command (e.g. `su ${USERNAME} -c "command-goes-here"`). In combination, this allows both root and non-root image modifications to occur even if `sudo` is not present in the base image for security reasons.
To ensure that the appropriate shell is used, the execute bit should be set on `install.sh` and the file invoked directly (e.g. `chmod +x install.sh && ./install.sh`).
-> **Note:** It is recommended that Feature authors write `install.sh` using a shell available by default in their supported distributions (e.g., `bash` in Debian/Ubuntu or Fedora, `sh` in Alpine). In the event a different shell is required (e.g., `fish`), `install.sh` can be used to boostrap by checking for the presence of the desired shell, installing it if needed, and then invoking a secondary script using the shell.
+> **Note:** It is recommended that Feature authors write `install.sh` using a shell available by default in their supported distributions (e.g. `bash` in Debian/Ubuntu or Fedora, `sh` in Alpine). In the event a different shell is required (e.g. `fish`), `install.sh` can be used to boostrap by checking for the presence of the desired shell, installing it if needed, and then invoking a secondary script using the shell.
>
-> The `install.sh` file can similarly be used to bootstrap something written in a compiled language like Go. Given the increasing likelihood that a Feature needs to work on both x86_64 and arm64-based devices (e.g., Apple Silicon Macs), `install.sh` can detect the current architecture (e.g., using something like `uname -m` or `dpkg --print-architecture`), and then invoke the right executable for that architecture.
+> The `install.sh` file can similarly be used to bootstrap something written in a compiled language like Go. Given the increasing likelihood that a Feature needs to work on both x86_64 and arm64-based devices (e.g. Apple Silicon Macs), `install.sh` can detect the current architecture (e.g. using something like `uname -m` or `dpkg --print-architecture`), and then invoke the right executable for that architecture.
### Installation order
@@ -271,9 +271,9 @@ If any of the following properties are provided in the Feature's `devcontainer-f
The optional `dependsOn` property indicates a set of required, "hard" dependencies for a given Feature.
-The `dependsOn` property is declared in a Feature's `devcontainer-feature.json` metadata file. Elements of this property mirror the semantics of the `features` object in `devcontainer.json`. Therefore, all dependencies may provide the relevant options, or an empty object (eg: `"bar:123": {}`) if the Feature's default options are sufficient. Identical Features that provide different options are treated as _different_ Features (see [Feature equality](#definition-feature-equality) for more info).
+The `dependsOn` property is declared in a Feature's `devcontainer-feature.json` metadata file. Elements of this property mirror the semantics of the `features` object in `devcontainer.json`. Therefore, all dependencies may provide the relevant options, or an empty object (e.g. `"bar:123": {}`) if the Feature's default options are sufficient. Identical Features that provide different options are treated as _different_ Features (see [Feature equality](#definition-feature-equality) for more info).
-All Features indicated in the `dependsOn` property **must** be satisfied (a Feature [equal](#definition-feature-equality) to each dependency is present in the installation order) _before_ the given Feature is set to be installed. If any of the Features indicated in the `dependsOn` property cannot be installed (e.g due to circular dependency, failure to resolve the Feature, etc) the entire dev container creation should fail.
+All Features indicated in the `dependsOn` property **must** be satisfied (a Feature [equal](#definition-feature-equality) to each dependency is present in the installation order) _before_ the given Feature is set to be installed. If any of the Features indicated in the `dependsOn` property cannot be installed (e.g. due to circular dependency, failure to resolve the Feature, etc) the entire dev container creation should fail.
The `dependsOn` property must be evaluated recursively. Therefore, if a Feature dependency has its own `dependsOn` property, that Feature's dependencies must also be satisfied before the given Feature is installed.
@@ -300,7 +300,7 @@ The `installsAfter` property indicates a "soft dependency" that influences the i
- `installsAfter` is **not** evaluated recursively.
- `installsAfter` only influences the installation order of Features that are **already set to be installed**. Any Feature not set to be installed after (1) resolving the `dependsOn` dependency tree or (2) indicated by the user's `devcontainer.json` should not be added to the installation list.
-- The Feature indicated by `installsAfter` can **not** provide options, nor are they able to be pinned to a specific version tag or digest. Resolution to the canonical name should still be performed (eg: If the Feature has been [renamed](#steps-to-rename-a-feature)).
+- The Feature indicated by `installsAfter` can **not** provide options, nor are they able to be pinned to a specific version tag or digest. Resolution to the canonical name should still be performed (e.g. if the Feature has been [renamed](#steps-to-rename-a-feature)).
```
{
@@ -350,7 +350,7 @@ This property must not influence the dependency relationship as defined by the d
Similar to `installsAfter`, this property's members may not provide options, nor are they able to be pinned to a specific version tag or digest.
-If a Feature is indicated in `overrideFeatureInstallOrder` but not a member of the dependency graph (it is not queued to be installed), the orchestrating tool may fail the dependency resolution step.
+If a Feature is indicated in `overrideFeatureInstallOrder` but not a member of the dependency graph (i.e. it is not queued to be installed), the orchestrating tool may fail the dependency resolution step.
> ## Definitions
> ### Definition: Feature Equality
@@ -414,7 +414,7 @@ If a Feature is indicated in `overrideFeatureInstallOrder` but not a member of t
>
> From an implementation point of view, `installsAfter` nodes may be added as a separate set of directed edges, just as `dependsOn` nodes are added as directed edges (see **(1)**). Before round-based installation and sorting **(3)**, an orchestrating tool should remove all `installsAfter` directed edges that do not correspond with a Feature in the `worklist` that is set to be installed. In each round, a Feature can then be installed if all its requirements (both `dependsOn` and `installsAfter` dependencies) have been fulfilled in previous rounds.
>
-> An implemention should fail the dependency resolution step if the evaluation of the `installsAfter` property results in an inconsistent state (eg: a circular dependency).
+> An implemention should fail the dependency resolution step if the evaluation of the `installsAfter` property results in an inconsistent state (e.g. a circular dependency).
>
diff --git a/docs/specs/devcontainer-id-variable.md b/docs/specs/devcontainer-id-variable.md
index 1f7ee612..cf225ebf 100644
--- a/docs/specs/devcontainer-id-variable.md
+++ b/docs/specs/devcontainer-id-variable.md
@@ -22,9 +22,9 @@ Implementations can choose how to compute this identifier. They must ensure that
The following assumes that a dev container can be identified among other dev containers on the same Docker host by a set of labels on the container. Implementations may choose to follow this approach.
-The identifier is derived from the set of container labels uniquely identifying the dev container. It is up to the implementation to choose these labels. E.g., if the dev container is based on a local folder the label could be named `devcontainer.local_folder` and have the local folder's path as its value.
+The identifier is derived from the set of container labels uniquely identifying the dev container. It is up to the implementation to choose these labels. For example, if the dev container is based on a local folder, the label could be named `devcontainer.local_folder` and have the local folder's path as its value.
-E.g., the [`ghcr.io/devcontainers/features/docker-in-docker` feature](https://github.com/devcontainers/features/blob/main/src/docker-in-docker/devcontainer-feature.json) could use the dev container id with:
+For example, the [`ghcr.io/devcontainers/features/docker-in-docker` feature](https://github.com/devcontainers/features/blob/main/src/docker-in-docker/devcontainer-feature.json) could use the dev container id with:
```jsonc
{
diff --git a/docs/specs/devcontainer-reference.md b/docs/specs/devcontainer-reference.md
index 0944621a..22ecab46 100644
--- a/docs/specs/devcontainer-reference.md
+++ b/docs/specs/devcontainer-reference.md
@@ -94,7 +94,7 @@ Variables in string values will be substituted at the time the value is applied.
- Passing the label as a command line argument:
- There is no size limit documented for labels, but the daemon returns an error when the request header is >500kb.
- The 500kb limit is shared, so we cannot use a second label in the same build to avoid it.
- - If/when this becomes an issue we could embed the metadata as a file in the image (e.g., with a label indicating it).
+ - If/when this becomes an issue we could embed the metadata as a file in the image (e.g. with a label indicating it).
# Orchestration options
@@ -139,7 +139,7 @@ A complete list of available metadata properties and their purposes can be found
Environment variables can be set at different points in the dev container lifecycle. With this in mind, **development containers** support two classes of environment variables:
* **Container**: These variables are part of the container when it is created and are available at all points in its lifecycle. This concept is native to containers and can be set in the container image itself, using `containerEnv` for **image** and **Dockerfile** scenarios or using orchestrator specific properties like `env` in **Docker Compose** files.
-* **Remote**: These variables should be set by a **development container** supporting tool as part of configuring its runtime environment. Users can set these using the `remoteEnv` property and implementing tools or services may add their own for specific scenarios (e.g., secrets). These variables can change during the lifetime of the container, and are added after the container's `ENTRYPOINT` has fired.
+* **Remote**: These variables should be set by a **development container** supporting tool as part of configuring its runtime environment. Users can set these using the `remoteEnv` property and implementing tools or services may add their own for specific scenarios (e.g. secrets). These variables can change during the lifetime of the container, and are added after the container's `ENTRYPOINT` has fired.
The reason for this separation is it allows for the use of information not available at image build time and simplifies updating the environment for project/repository specific needs without modifying an image. With this in in mind, it's important to note that implementing tools should also support the [dynamic variable syntax](devcontainerjson-reference.md#variables-in-devcontainerjson) described in the metadata reference document.
@@ -240,7 +240,7 @@ Any user facing processes should have remote [environment variables](#environmen
For example, in the [CLI reference implementation](https://github.com/devcontainers/cli), this is the point in which anything executed with `devcontainer exec` would run.
-Typically, this is also the step where implementors would apply config or settings from the `customizations` section of the dev container metadata (e.g., VS Code installs extensions based on the `customizations.vscode.extensions` property). Examples of these can be found in the [supporting tools section](supporting-tools.md) reference. However, applying these at this point is not strictly required or mandated by this specification.
+Typically, this is also the step where implementors would apply config or settings from the `customizations` section of the dev container metadata (e.g. VS Code installs extensions based on the `customizations.vscode.extensions` property). Examples of these can be found in the [supporting tools section](supporting-tools.md) reference. However, applying these at this point is not strictly required or mandated by this specification.
Once these final steps have occurred, implementing tools or services may connect to the environment as they see fit.
diff --git a/docs/specs/devcontainer-templates-distribution.md b/docs/specs/devcontainer-templates-distribution.md
index d058bf10..71444720 100644
--- a/docs/specs/devcontainer-templates-distribution.md
+++ b/docs/specs/devcontainer-templates-distribution.md
@@ -114,7 +114,7 @@ done
```
-The "namespace" is the globally identifiable name for the collection of Templates. (eg: `owner/repo` for the source code's git repository).
+The "namespace" is the globally identifiable name for the collection of Templates (e.g. `owner/repo` for the source code's git repository).
The auto-generated `devcontainer-collection.json` is pushed to the registry with the same `namespace` as above and no accompanying `template` name. The collection file is always tagged as `latest`.
diff --git a/docs/specs/devcontainer-templates.md b/docs/specs/devcontainer-templates.md
index 7e53f6e4..5b264ad1 100644
--- a/docs/specs/devcontainer-templates.md
+++ b/docs/specs/devcontainer-templates.md
@@ -2,7 +2,7 @@
**Development Container Templates** are source files packaged together that encode configuration for a complete development environment. A Template can be used in a new or existing project, and a [supporting tool](https://containers.dev/supporting) will use the configuration from the Template to build a development container.
-The configuration is placed in a [`.devcontainer/devcontainer.json`](/docs/specs/devcontainer-reference.md#devcontainerjson) which can also reference other files within the Template. A Template can also provide additional source files (eg: boilerplate code or a [lifecycle script](https://containers.dev/implementors/json_reference/#lifecycle-scripts).
+The configuration is placed in a [`.devcontainer/devcontainer.json`](/docs/specs/devcontainer-reference.md#devcontainerjson) which can also reference other files within the Template. A Template can also provide additional source files (e.g. boilerplate code or a [lifecycle script](https://containers.dev/implementors/json_reference/#lifecycle-scripts).
Template metadata is captured by a `devcontainer-template.json` file in the root folder of the Template.
@@ -37,7 +37,7 @@ The properties of the file are as follows:
| `platforms` | array | Languages and platforms supported by the Template. |
| `publisher` | string | Name of the publisher/maintainer of the Template. |
| `keywords` | array | List of strings relevant to a user that would search for this Template. |
-| [`optionalPaths`](#the-optionalpaths-property) | array | An array of files or directories that tooling may consider "optional" when applying a Template. Directories are indicated with a trailing `/*`, (eg: `.github/*`).
+| [`optionalPaths`](#the-optionalpaths-property) | array | An array of files or directories that tooling may consider "optional" when applying a Template. Directories are indicated with a trailing `/*` (e.g. `.github/*`).
### The `options` property
diff --git a/docs/specs/devcontainerjson-reference.md b/docs/specs/devcontainerjson-reference.md
index a479b5eb..fa3893b1 100644
--- a/docs/specs/devcontainerjson-reference.md
+++ b/docs/specs/devcontainerjson-reference.md
@@ -97,7 +97,7 @@ The `portsAttributes` and `otherPortsAttributes` properties allow you to map def
| Property | Type | Description |
|----------|------|-------------|
| `label` 🏷️ | string | Display name for the port in the ports view. Defaults to not set. |
-| `protocol` 🏷️ | enum | Controls protocol handling for forwarded ports. When not set, the port is assumed to be a raw TCP stream which, if forwarded to `localhost`, supports any number of protocols. However, if the port is forwarded to a web URL (e.g. from a cloud service on the web), only HTTP ports in the container are supported. Setting this property to `https` alters handling by ignoring any SSL/TLS certificates present when communicating on the port and using the correct certificate for the forwarded URL instead (e.g `https://*.githubpreview.dev`). If set to `http`, processing is the same as if the protocol is not set. Defaults to not set. |
+| `protocol` 🏷️ | enum | Controls protocol handling for forwarded ports. When not set, the port is assumed to be a raw TCP stream which, if forwarded to `localhost`, supports any number of protocols. However, if the port is forwarded to a web URL (e.g. from a cloud service on the web), only HTTP ports in the container are supported. Setting this property to `https` alters handling by ignoring any SSL/TLS certificates present when communicating on the port and using the correct certificate for the forwarded URL instead (e.g. `https://*.githubpreview.dev`). If set to `http`, processing is the same as if the protocol is not set. Defaults to not set. |
| `onAutoForward` 🏷️ | enum | Controls what should happen when a port is auto-forwarded once you've connected to the container. `notify` is the default, and a notification will appear when the port is auto-forwarded. If set to `openBrowser`, the port will be opened in the system's default browser. A value of `openBrowserOnce` will open the browser only once. `openPreview` will open the URL in `devcontainer.json` supporting services' / tools' embedded preview browser. A value of `silent` will forward the port, but take no further action. A value of `ignore` means that this port should not be auto-forwarded at all. |
| `requireLocalPort` 🏷️ | boolean | Dictates when port forwarding is required to map the port in the container to the same port locally or not. If set to `false`, the `devcontainer.json` supporting services / tools will attempt to use the specified port forward to `localhost`, and silently map to a different one if it is unavailable. If set to `true`, you will be notified if it is not possible to use the same port. Defaults to `false`. |
| `elevateIfNeeded` 🏷️ | boolean | Forwarding low ports like 22, 80, or 443 to `localhost` on the same port from `devcontainer.json` supporting services / tools may require elevated permissions on certain operating systems. Setting this property to `true` will automatically try to elevate the `devcontainer.json` supporting tool's permissions in this situation. Defaults to `false`. |
diff --git a/docs/specs/feature-dependencies.md b/docs/specs/feature-dependencies.md
index 60601ad2..a50a9323 100644
--- a/docs/specs/feature-dependencies.md
+++ b/docs/specs/feature-dependencies.md
@@ -37,14 +37,14 @@ A new property `dependsOn` can be optionally added to the `devcontainer-feature.
> This property is similar to the existing `installsAfter` property, with the key distinctions that `installsAfter` (1) is **not** recursive, (2) indicates a soft dependency to influence installation order **if and only if a given Feature is already set to be installed via a user-defined Feature or transitively through a user-defined Feature**, and (3) Features indicated by `installsAfter` can not provide options, nor are they able to be pinned to a specific version tag or digest.
-The installation order is subject to the algorithm set forth in this document. Where there is ambiguity, it is up to the orchestrating tool to decide the order of installation. Implementing tools should provide a consistent installation order in instances of ambiguity (i.e sort alphanumerically by identifier).
+The installation order is subject to the algorithm set forth in this document. Where there is ambiguity, it is up to the orchestrating tool to decide the order of installation. Implementing tools should provide a consistent installation order in instances of ambiguity (i.e. sort alphanumerically by identifier).
| Property | Type | Description |
|----------|------|-------------|
| `dependsOn` | `object` | The ID and options of the Feature dependency. Pinning to version tags or digests are honored. When published, the ID must refer to either a Feature (1) published to an OCI registry, (2) a Feature Tgz URI, or (3) a Feature in the local file tree (**). Otherwise, IDs follow the same semantics of the `features` object in `devcontainer.json`. (a.k.a "Hard Dependency") |
-(**) Deprecated Feature identifiers (i.e GitHub Release) are not supported and the presence of this property may be considered a fatal error or ignored. For [local Features (ie: during development)](https://containers.dev/implementors/features-distribution/#addendum-locally-referenced), you may also depend on other local Features by providing a relative path to the Feature, relative to folder containing the active `devcontainer.json`. This behavior of Features within this property again mirror the `features` object in `devcontainer.json`.
+(**) Deprecated Feature identifiers (i.e. GitHub Release) are not supported and the presence of this property may be considered a fatal error or ignored. For [local Features (i.e. during development)](https://containers.dev/implementors/features-distribution/#addendum-locally-referenced), you may also depend on other local Features by providing a relative path to the Feature, relative to folder containing the active `devcontainer.json`. This behavior of Features within this property again mirror the `features` object in `devcontainer.json`.
An example `devcontainer-feature.json` file with a dependency on four other published Features:
@@ -103,7 +103,7 @@ An example manifest with the `dev.containers.metadata` annotation:
}
```
-> If no annotation is present on a Feature's manifest, the orchestrating tool MUST fallback to downloading and extracting the Feature's contents to read the metadata properties. Failure to do so may result in a Feature being installed without its dependencies (eg: `installsAfter`).
+> If no annotation is present on a Feature's manifest, the orchestrating tool MUST fallback to downloading and extracting the Feature's contents to read the metadata properties. Failure to do so may result in a Feature being installed without its dependencies (e.g. `installsAfter`).
In summary, supporting tools may choose to identify the dependencies of the declared user-defined Features by fetching the manifest of the Features and reading the `dependsOn` and `installsAfter` properties from the `dev.containers.metadata` annotation. This will allow the orchestrating tool to recursively resolve all dependencies without having to download and extract each Feature's tarball.
@@ -186,7 +186,7 @@ The `installsAfter` property is a "soft dependency" that influences the installa
From an implementation point of view, `installsAfter` nodes may be added as a seperate set of directed edges, just as `dependsOn` nodes are added as directed edges (see **(B1)**). Before round-based installation and sorting **(B3)**, an orchestrating tool should remove all `installsAfter` directed edges that do not correspond with a Feature in the `worklist` that is set to be installed. In each round, a Feature can then be installed if all its requirements (both `dependsOn` and `installsAfter` dependencies) have been fulfilled in previous rounds.
-An implemention should fail the dependency resolution step if the evaluation of the `installsAfter` property results in an inconsistent state (eg: a circular dependency).
+An implemention should fail the dependency resolution step if the evaluation of the `installsAfter` property results in an inconsistent state (e.g. a circular dependency).
### overrideFeatureInstallOrder
@@ -220,7 +220,7 @@ This property must not influence the dependency relationship as defined by the d
Similar to `installsAfter`, this property's members may not provide options, nor are they able to be pinned to a specific version tag or digest. This is unchanged from the current specification.
-If a Feature is indicated in `overrideFeatureInstallOrder` but not a member of the dependency graph (it is not queued to be installed), the orchestrating tool may fail the dependency resolution step.
+If a Feature is indicated in `overrideFeatureInstallOrder` but not a member of the dependency graph (i.e. it is not queued to be installed), the orchestrating tool may fail the dependency resolution step.
## Additional Remarks
@@ -230,7 +230,7 @@ Features should be authored with the following considerations:
- Features should be authored with the assumption that they will be installed in any order, so long as the dependencies are met at some point beforehand.
- Since two Features with different options are considered different, a single Feature may be installed more than once. Features should be idempotent.
-- Features that require updating shared state in the container (eg: updating the `$PATH`), should be aware that the same Feature may be run multiple times. Consider a method for previous runs of the Feature to communicate with future runs, updating the shared state in the intended way.
+- Features that require updating shared state in the container (e.g. updating the `$PATH`), should be aware that the same Feature may be run multiple times. Consider a method for previous runs of the Feature to communicate with future runs, updating the shared state in the intended way.
### Image Metadata
diff --git a/docs/specs/features-legacyIds-deprecated-properties.md b/docs/specs/features-legacyIds-deprecated-properties.md
index 16b6728e..e8d3a375 100644
--- a/docs/specs/features-legacyIds-deprecated-properties.md
+++ b/docs/specs/features-legacyIds-deprecated-properties.md
@@ -60,7 +60,7 @@ We'd want to rename this Feature to `docker-outside-of-docker`. The source code
#### Changes to the Features distribution specification
-- [Tools implementing the Dev Container Features Distribution Specification](../docs/specs/features-distribution/#distribution) (eg: [Dev Container CLI](https://github.com/devcontainers/cli) and [Dev Container Publish GitHub Action](https://github.com/marketplace/actions/dev-container-publish)) will dual publish the old `id`s (defined by the `legacyIds` property), and the new `id`.
+- [Tools implementing the Dev Container Features Distribution Specification](../docs/specs/features-distribution/#distribution) (e.g. [Dev Container CLI](https://github.com/devcontainers/cli) and [Dev Container Publish GitHub Action](https://github.com/marketplace/actions/dev-container-publish)) will dual publish the old `id`s (defined by the `legacyIds` property), and the new `id`.
- The [putManifestWithTags](https://github.com/devcontainers/cli/blob/main/src/spec-configuration/containerCollectionsOCIPush.ts#L172) will be modified. The same `tgz` file for the `id` will be pushed to the `id`s mentioned by the `legacyIds` property for all the [tags](https://github.com/devcontainers/cli/blob/main/src/spec-configuration/containerCollectionsOCIPush.ts#L175).
#### Supporting backwards compatibility for [`installsAfter`](../docs/specs/devcontainer-features.md#2-the-installsafter-feature-property) property
diff --git a/docs/specs/secrets-support.md b/docs/specs/secrets-support.md
index 425c2fc8..ff0575af 100644
--- a/docs/specs/secrets-support.md
+++ b/docs/specs/secrets-support.md
@@ -22,7 +22,7 @@ Today many consumers pass secret variables as `remoteEnv`, since there are no ot
## Proposal
-A [supporting tool](https://containers.dev/supporting#tools) (ie, for example the [dev container CLI reference implementation](https://github.com/devcontainers/cli)) should behave according to the following properties:
+A [supporting tool](https://containers.dev/supporting#tools) (e.g. the [dev container CLI reference implementation](https://github.com/devcontainers/cli)) should behave according to the following properties:
1. Ability to pass secrets to commands
2. Apply/use secrets similar to `remoteEnv`
From b319b50e320ed26177e49fd6df3c52ab347b5a46 Mon Sep 17 00:00:00 2001
From: Hossein Abbasi <16090309+hsnabszhdn@users.noreply.github.com>
Date: Fri, 4 Jul 2025 12:27:31 +1000
Subject: [PATCH 04/13] Fix note and tip blocks
---
docs/specs/devcontainer-features.md | 4 ++--
docs/specs/devcontainer-templates.md | 2 +-
docs/specs/features-contribute-lifecycle-scripts.md | 2 +-
docs/specs/supporting-tools.md | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/docs/specs/devcontainer-features.md b/docs/specs/devcontainer-features.md
index 844575a8..1e0cf311 100644
--- a/docs/specs/devcontainer-features.md
+++ b/docs/specs/devcontainer-features.md
@@ -72,7 +72,7 @@ For each lifecycle hook (in [Feature installation order](https://containers.dev/
If a Feature provides a given command with the [object syntax](/docs/specs/devcontainerjson-reference.md#formatting-string-vs-array-properties), all commands within that group are executed in parallel, but still blocking commands from subsequent Features and/or the `devcontainer.json`.
-> NOTE: These properties are stored within [image metadata](https://github.com/devcontainers/spec/blob/joshspicer/lifecycle_hook_feature_spec/docs/specs/devcontainer-reference.md#merge-logic).
+> **Note:** These properties are stored within [image metadata](https://github.com/devcontainers/spec/blob/joshspicer/lifecycle_hook_feature_spec/docs/specs/devcontainer-reference.md#merge-logic).
### The `options` property
@@ -190,7 +190,7 @@ Below is a valid `features` object provided as an example.
}
```
-> Note: The `:latest` version annotation is added implicitly if omitted. To pin to a specific package version ([example](https://github.com/devcontainers/features/pkgs/container/features/go/versions)), append it to the end of the Feature.
+> **Note:** The `:latest` version annotation is added implicitly if omitted. To pin to a specific package version ([example](https://github.com/devcontainers/features/pkgs/container/features/go/versions)), append it to the end of the Feature.
An option's value can be provided as either a `string` or `boolean`, and should match what is expected by the Feature in the `devcontainer-feature.json` file.
diff --git a/docs/specs/devcontainer-templates.md b/docs/specs/devcontainer-templates.md
index 7e53f6e4..d9cb5508 100644
--- a/docs/specs/devcontainer-templates.md
+++ b/docs/specs/devcontainer-templates.md
@@ -65,7 +65,7 @@ The `options` property contains a map of option IDs and their related configurat
| `optionId.enum` | array | A strict list of allowed string values. Free-form values are **not** allowed. Omit when using `optionId.proposals`. |
| `optionId.default` | string | Default value for the option. |
-> `Note`: The `options` must be unique for every `devcontainer-template.json`
+> **Note:** The `options` must be unique for every `devcontainer-template.json`
### The `optionalPaths` property
diff --git a/docs/specs/features-contribute-lifecycle-scripts.md b/docs/specs/features-contribute-lifecycle-scripts.md
index 17414578..e77116e0 100644
--- a/docs/specs/features-contribute-lifecycle-scripts.md
+++ b/docs/specs/features-contribute-lifecycle-scripts.md
@@ -24,7 +24,7 @@ Note that `initializeCommand` is omitted, pending further discussions around a s
As with all lifecycle hooks, commands are executed from the context (cwd) of the [project workspace folder](https://containers.dev/implementors/spec/#project-workspace-folder).
-> NOTE: To use any assets (a script, etc...) embedded within a Feature in a lifecycle hook property, it is the Feature author's reponsibility to copy that assert to somewhere on the container where it will persist (outside of `/tmp`.) Implementations are not required to persist Feature install scripts beyond the initial build.
+> **Note:** To use any assets (a script, etc...) embedded within a Feature in a lifecycle hook property, it is the Feature author's reponsibility to copy that assert to somewhere on the container where it will persist (outside of `/tmp`.) Implementations are not required to persist Feature install scripts beyond the initial build.
All other semantics match the existing [Lifecycle Scripts](https://containers.dev/implementors/json_reference/#lifecycle-scripts) and [lifecycle script parallel execution](https://containers.dev/implementors/spec/#parallel-exec) behavior exactly.
diff --git a/docs/specs/supporting-tools.md b/docs/specs/supporting-tools.md
index 40c40f2e..9db07b64 100644
--- a/docs/specs/supporting-tools.md
+++ b/docs/specs/supporting-tools.md
@@ -83,7 +83,7 @@ A [codespace](https://docs.github.com/en/codespaces/overview) is a development e
> **Tip:** If you've already built a codespace and connected to it, be sure to run **Codespaces: Rebuild Container** from the Command Palette (`kbstyle(F1)`) to pick up any changes you make.
-> **Tip** Codespaces implements an auto `workspaceFolder` mount in **Docker Compose** scenarios.
+> **Tip:** Codespaces implements an auto `workspaceFolder` mount in **Docker Compose** scenarios.
#### Product specific properties
GitHub Codespaces works with a growing number of tools and, where applicable, their `devcontainer.json` properties. For example, connecting the codespaces web editor or VS Code enables the use of [VS Code properties](#visual-studio-code).
From b5db21285bcfe28ab77ee0edf62d8de02dc2f6e0 Mon Sep 17 00:00:00 2001
From: Hossein Abbasi <16090309+hsnabszhdn@users.noreply.github.com>
Date: Fri, 4 Jul 2025 12:36:35 +1000
Subject: [PATCH 05/13] Fix sentence structures
---
docs/specs/devcontainer-features-distribution.md | 2 +-
docs/specs/devcontainer-features.md | 2 +-
docs/specs/devcontainer-reference.md | 4 ++--
docs/specs/devcontainer-templates-distribution.md | 2 +-
docs/specs/feature-dependencies.md | 2 +-
5 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/docs/specs/devcontainer-features-distribution.md b/docs/specs/devcontainer-features-distribution.md
index e2c09615..baf693db 100644
--- a/docs/specs/devcontainer-features-distribution.md
+++ b/docs/specs/devcontainer-features-distribution.md
@@ -49,7 +49,7 @@ Source code for the set follows the example file structure below:
...where `src` is a directory containing a sub-folder with the name of the Feature (e.g. `src/dotnet` or `src/go`) with at least a file named `devcontainer-feature.json` that contains the Feature metadata, and an `install.sh` script that implementing tools will use as the entrypoint to install the Feature.
-Each sub-directory should be named such that it matches the `id` field of the `devcontainer-feature.json`. Other files can also be included in the Feature's sub-directory, and will be included during the [packaging step](#packaging) alongside the two required files. Any files that are not part of the Feature's sub-directory (e.g. outside of `src/dotnet`) will not included in the [packaging step](#packaging).
+Each sub-directory should be named such that it matches the `id` field of the `devcontainer-feature.json`. Other files can also be included in the Feature's sub-directory, and will be included during the [packaging step](#packaging) alongside the two required files. Any files that are not part of the Feature's sub-directory (e.g. outside of `src/dotnet`) will not be included in the [packaging step](#packaging).
Optionally, a mirrored `test` directory can be included with an accompanying `test.sh` script. Implementing tools may use this to run tests against the given Feature.
diff --git a/docs/specs/devcontainer-features.md b/docs/specs/devcontainer-features.md
index 844575a8..69bebb7f 100644
--- a/docs/specs/devcontainer-features.md
+++ b/docs/specs/devcontainer-features.md
@@ -322,7 +322,7 @@ The `overrideFeatureInstallOrder` property of `devcontainer.json` is an array of
> This property may not indicate an installation order that is inconsistent with the resolved dependency graph (see [dependency algorithm](#dependency-installation-order-algorithm)). If the `overrideFeatureInstallOrder` property is inconsistent with the dependency graph, the implementing tool should fail the dependency resolution step.
-This evaluation is performed by assigning a [`roundPriority`](#2-assigning-round-priority) to all nodes that match match the Feature identifier (version omitted) present in the property.
+This evaluation is performed by assigning a [`roundPriority`](#2-assigning-round-priority) to all nodes that match the Feature identifier (version omitted) present in the property.
For example, given `n` Features in the `overrideFeatureInstallOrder` array, the orchestrating tool should assign a `roundPriority` of `n - idx` to each Feature, where `idx` is the zero-based index of the Feature in the array.
diff --git a/docs/specs/devcontainer-reference.md b/docs/specs/devcontainer-reference.md
index 0944621a..b0b11322 100644
--- a/docs/specs/devcontainer-reference.md
+++ b/docs/specs/devcontainer-reference.md
@@ -141,7 +141,7 @@ Environment variables can be set at different points in the dev container lifecy
* **Container**: These variables are part of the container when it is created and are available at all points in its lifecycle. This concept is native to containers and can be set in the container image itself, using `containerEnv` for **image** and **Dockerfile** scenarios or using orchestrator specific properties like `env` in **Docker Compose** files.
* **Remote**: These variables should be set by a **development container** supporting tool as part of configuring its runtime environment. Users can set these using the `remoteEnv` property and implementing tools or services may add their own for specific scenarios (e.g., secrets). These variables can change during the lifetime of the container, and are added after the container's `ENTRYPOINT` has fired.
-The reason for this separation is it allows for the use of information not available at image build time and simplifies updating the environment for project/repository specific needs without modifying an image. With this in in mind, it's important to note that implementing tools should also support the [dynamic variable syntax](devcontainerjson-reference.md#variables-in-devcontainerjson) described in the metadata reference document.
+The reason for this separation is it allows for the use of information not available at image build time and simplifies updating the environment for project/repository specific needs without modifying an image. With this in mind, it's important to note that implementing tools should also support the [dynamic variable syntax](devcontainerjson-reference.md#variables-in-devcontainerjson) described in the metadata reference document.
Another notable and important environment variable related property is **`userEnvProbe`**. Implementing tools should use this property to "probe" for expected environment variables using the specified type of shell. However, it does not specify that this type of shell needs to be used for all sub-processes (given the performance impact). Instead, "probed" environment variables should be merged with Remote environment variables for any processes the implementer injects after the container is created. This allows implementors to emulate developer expected behaviors around values added to their profile and rc files.
@@ -159,7 +159,7 @@ Inside the container this mount defaults to `/workspace`.
The default mount point for the source code can be set with the `workspaceMount` property for **image** and **dockerfile** scenarios or using the built in `mounts` property in **Docker Compose** files. This folder should point to the root of a repository (where the `.git` folder is found) so that source control operations work correctly inside the container.
-The `workspaceFolder` can then be set to the default folder inside the container that should used in the container. Typically this is either the mount point in the container, or a sub-folder under it. Allowing a sub-folder to be used is particularly important for monorepos given you need the `.git` folder to interact with source control but developers are typically are interacting with a specific sub-project within the overall repository.
+The `workspaceFolder` can then be set to the default folder inside the container that should used in the container. Typically this is either the mount point in the container, or a sub-folder under it. Allowing a sub-folder to be used is particularly important for monorepos given you need the `.git` folder to interact with source control but developers are typically interacting with a specific sub-project within the overall repository.
See [`workspaceMount` and `workspaceFolder`](devcontainerjson-reference.md#image-or-dockerfile-specific-properties) for reference.
diff --git a/docs/specs/devcontainer-templates-distribution.md b/docs/specs/devcontainer-templates-distribution.md
index d058bf10..b3814af6 100644
--- a/docs/specs/devcontainer-templates-distribution.md
+++ b/docs/specs/devcontainer-templates-distribution.md
@@ -50,7 +50,7 @@ Source code for a set of Templates follows the example file structure below:
...where `src` is a directory containing a sub-folder with the name of the Template (e.g. `src/dotnet` or `src/docker-from-docker`) with at least a file named `devcontainer-template.json` that contains the Template metadata, and a `.devcontainer/devcontainer.json` that the supporting tools will drop into an existing project or folder.
-Each sub-directory should be named such that it matches the `id` field of the `devcontainer-template.json`. Other files can also be included in the Templates's sub-directory, and will be included during the [packaging step](#packaging) alongside the two required files. Any files that are not part of the Templates's sub-directory (e.g. outside of `src/dotnet`) will not included in the [packaging step](#packaging).
+Each sub-directory should be named such that it matches the `id` field of the `devcontainer-template.json`. Other files can also be included in the Templates's sub-directory, and will be included during the [packaging step](#packaging) alongside the two required files. Any files that are not part of the Templates's sub-directory (e.g. outside of `src/dotnet`) will not be included in the [packaging step](#packaging).
## Versioning
diff --git a/docs/specs/feature-dependencies.md b/docs/specs/feature-dependencies.md
index 60601ad2..b5d27251 100644
--- a/docs/specs/feature-dependencies.md
+++ b/docs/specs/feature-dependencies.md
@@ -192,7 +192,7 @@ An implemention should fail the dependency resolution step if the evaluation of
The `overrideFeatureInstallOrder` property of `devcontainer.json` is an array of Feature IDs that are to be installed in descending priority order as soon as its dependencies outlined above are installed.
-This evaluation is performed by assigning a [`roundPriority`](#b2-assigning-roundpriority) to all nodes that match match the Feature identifier present in the property.
+This evaluation is performed by assigning a [`roundPriority`](#b2-assigning-roundpriority) to all nodes that match the Feature identifier present in the property.
For example, given `n` Features in the `overrideFeatureInstallOrder` array, the orchestrating tool should assign a `roundPriority` of `n - idx` to each Feature, where `idx` is the zero-based index of the Feature in the array.
From 9a20b5bceb4d834152df8995839cf99ff8c0591e Mon Sep 17 00:00:00 2001
From: Hossein Abbasi <16090309+hsnabszhdn@users.noreply.github.com>
Date: Fri, 4 Jul 2025 13:02:10 +1000
Subject: [PATCH 06/13] Fix fat-finger incidents
---
docs/specs/devcontainer-features.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/docs/specs/devcontainer-features.md b/docs/specs/devcontainer-features.md
index 844575a8..4cd74eff 100644
--- a/docs/specs/devcontainer-features.md
+++ b/docs/specs/devcontainer-features.md
@@ -355,11 +355,11 @@ If a Feature is indicated in `overrideFeatureInstallOrder` but not a member of t
> ## Definitions
> ### Definition: Feature Equality
>
-> This specification defines two Features as equal if both Features point to the same exact contents and are executed with > the same options.
+> This specification defines two Features as equal if both Features point to the same exact contents and are executed with the same options.
>
-> **For Features published to an OCI registry**, two Feature are identical if their manifest digests are equal, and the > options executed against the Feature are equal (compared value by value). Identical manifest digests implies that the tgz contents of the Feature and its entire `devcontainer-feature.json` are identical. If any of these conditions are not met, the Features are considered not equal.
+> **For Features published to an OCI registry**, two Feature are identical if their manifest digests are equal, and the options executed against the Feature are equal (compared value by value). Identical manifest digests implies that the tgz contents of the Feature and its entire `devcontainer-feature.json` are identical. If any of these conditions are not met, the Features are considered not equal.
>
-> **For Features fetched by HTTPS URI**, two Features are identical if the contents of the tgz are identical (hash to the > same value), and the options executed against the Feature are equal (compared value by value). If any of these conditions are not met, the Features are considered not equal.
+> **For Features fetched by HTTPS URI**, two Features are identical if the contents of the tgz are identical (hash to the same value), and the options executed against the Feature are equal (compared value by value). If any of these conditions are not met, the Features are considered not equal.
>
> **For local Features**, each Feature is considered unique and not equal to any other local Feature.
>
@@ -394,7 +394,7 @@ If a Feature is indicated in `overrideFeatureInstallOrder` but not a member of t
>
> Each node in the graph has an implicit, default `roundPriority` of 0.
>
-> To influence installation order globally while still honoring the dependency graph of built in **(1)**, `roundPriority` values may be tweaks for each Feature. When each round is calculated in **(3)**, only the Features equal to the max `roundPriority` of that set will be committed (the remaining will be > uncommitted and reevaulated in subsequent rounds).
+> To influence installation order globally while still honoring the dependency graph of built in **(1)**, `roundPriority` values may be tweaks for each Feature. When each round is calculated in **(3)**, only the Features equal to the max `roundPriority` of that set will be committed (the remaining will be uncommitted and reevaulated in subsequent rounds).
>
> The `roundPriority` is set to a non-zero value in the following instances:
>
From b229d53c1038520b29bddb1965b22461f1642139 Mon Sep 17 00:00:00 2001
From: Hossein Abbasi <16090309+hsnabszhdn@users.noreply.github.com>
Date: Fri, 4 Jul 2025 13:04:35 +1000
Subject: [PATCH 07/13] Fix incorrect heading size
---
docs/specs/devcontainer-features.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/specs/devcontainer-features.md b/docs/specs/devcontainer-features.md
index 844575a8..86721f2c 100644
--- a/docs/specs/devcontainer-features.md
+++ b/docs/specs/devcontainer-features.md
@@ -400,7 +400,7 @@ If a Feature is indicated in `overrideFeatureInstallOrder` but not a member of t
>
> - If the [`devcontainer.json` contains an `overrideFeatureInstallOrder`](#the-overridefeatureinstallorder-property).
>
-> #### (3) Round-based sorting
+> ### (3) Round-based sorting
>
> Perform a sort on the result of **(1)** in rounds. This sort will rearrange Features, producing a sorted list of Features to install. The sort will be performed as follows:
>
From ecc54b9d805e4a2b195fe234e505d18f8033c1e3 Mon Sep 17 00:00:00 2001
From: Hossein Abbasi <16090309+hsnabszhdn@users.noreply.github.com>
Date: Fri, 4 Jul 2025 13:12:11 +1000
Subject: [PATCH 08/13] Fix paragraph continuation pattern
---
docs/specs/devcontainer-templates.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/specs/devcontainer-templates.md b/docs/specs/devcontainer-templates.md
index 7e53f6e4..5eea9651 100644
--- a/docs/specs/devcontainer-templates.md
+++ b/docs/specs/devcontainer-templates.md
@@ -163,7 +163,7 @@ Suppose the `java` Template has the following `options` parameters declared in t
}
```
-and it has the following `.devcontainer/devcontainer.json` file:
+...and it has the following `.devcontainer/devcontainer.json` file:
```json
{
From cbd2ae8ad7f71d93f43d44d7b530d100c308f4b6 Mon Sep 17 00:00:00 2001
From: Hossein Abbasi <16090309+hsnabszhdn@users.noreply.github.com>
Date: Fri, 4 Jul 2025 13:43:11 +1000
Subject: [PATCH 09/13] Remove articles for backtick'd words
---
docs/specs/devcontainer-features-distribution.md | 2 +-
docs/specs/devcontainer-templates-distribution.md | 2 +-
docs/specs/devcontainer-templates.md | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/specs/devcontainer-features-distribution.md b/docs/specs/devcontainer-features-distribution.md
index e2c09615..37e623e8 100644
--- a/docs/specs/devcontainer-features-distribution.md
+++ b/docs/specs/devcontainer-features-distribution.md
@@ -92,7 +92,7 @@ An OCI registry that implements the [OCI Artifact Distribution Specification](ht
Each packaged feature is pushed to the registry following the naming convention `//[:version]`, where version is the major, minor, and patch version of the Feature, according to the semver specification.
-> **Note:** The `namespace` is a unique identifier for the collection of Features. There are no strict rules for the `namespace`; however, one pattern is to set `namespace` equal to source repository's `/`. The `namespace` should be lowercase, following [the regex provided in the OCI specification](https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pulling-manifests).
+> **Note:** `namespace` is a unique identifier for the collection of Features. There are no strict rules for `namespace`; however, one pattern is to set `namespace` equal to source repository's `/`. The `namespace` should be lowercase, following [the regex provided in the OCI specification](https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pulling-manifests).
A custom media type `application/vnd.devcontainers` and `application/vnd.devcontainers.layer.v1+tar` are used as demonstrated below.
diff --git a/docs/specs/devcontainer-templates-distribution.md b/docs/specs/devcontainer-templates-distribution.md
index d058bf10..dc5f78de 100644
--- a/docs/specs/devcontainer-templates-distribution.md
+++ b/docs/specs/devcontainer-templates-distribution.md
@@ -89,7 +89,7 @@ An OCI registry that implements the [OCI Artifact Distribution Specification](ht
Each packaged Template is pushed to the registry following the naming convention `//[:version]`, where version is the major, minor, and patch version of the Template, according to the semver specification.
-> **Note:** The `namespace` is a unique identifier for the collection of Templates and must be different than the collection of [Features](./devcontainer-features.md). There are no strict rules for the `namespace`; however, one pattern is to set `namespace` equal to source repository's `/`.
+> **Note:** `namespace` is a unique identifier for the collection of Templates and must be different than the collection of [Features](./devcontainer-features.md). There are no strict rules for `namespace`; however, one pattern is to set `namespace` equal to source repository's `/`.
A custom media type `application/vnd.devcontainers` and `application/vnd.devcontainers.layer.v1+tar` are used as demonstrated below.
diff --git a/docs/specs/devcontainer-templates.md b/docs/specs/devcontainer-templates.md
index 7e53f6e4..fc97fce5 100644
--- a/docs/specs/devcontainer-templates.md
+++ b/docs/specs/devcontainer-templates.md
@@ -2,7 +2,7 @@
**Development Container Templates** are source files packaged together that encode configuration for a complete development environment. A Template can be used in a new or existing project, and a [supporting tool](https://containers.dev/supporting) will use the configuration from the Template to build a development container.
-The configuration is placed in a [`.devcontainer/devcontainer.json`](/docs/specs/devcontainer-reference.md#devcontainerjson) which can also reference other files within the Template. A Template can also provide additional source files (eg: boilerplate code or a [lifecycle script](https://containers.dev/implementors/json_reference/#lifecycle-scripts).
+The configuration is placed in [`.devcontainer/devcontainer.json`](/docs/specs/devcontainer-reference.md#devcontainerjson) which can also reference other files within the Template. A Template can also provide additional source files (eg: boilerplate code or a [lifecycle script](https://containers.dev/implementors/json_reference/#lifecycle-scripts).
Template metadata is captured by a `devcontainer-template.json` file in the root folder of the Template.
From 18b6f6655589ae1c046c740ec4a1b2ebe84cdab2 Mon Sep 17 00:00:00 2001
From: Hossein Abbasi <16090309+hsnabszhdn@users.noreply.github.com>
Date: Fri, 4 Jul 2025 13:52:01 +1000
Subject: [PATCH 10/13] Fix incorrect references
---
docs/specs/devcontainer-features.md | 2 +-
docs/specs/devcontainer-reference.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/specs/devcontainer-features.md b/docs/specs/devcontainer-features.md
index 844575a8..c001323d 100644
--- a/docs/specs/devcontainer-features.md
+++ b/docs/specs/devcontainer-features.md
@@ -314,7 +314,7 @@ The `installsAfter` property indicates a "soft dependency" that influences the i
}
```
-In the snippet above, `myfeature` must be installed after `foo` and `bar` **if** the Feature is already queued to be installed. If `second` and `third` are not already queued to be installed, this dependency relationship should be ignored.
+In the snippet above, `myfeature` must be installed after `foo` and `bar` **if** the Feature is already queued to be installed. If `foo` and `bar` are not already queued to be installed, this dependency relationship should be ignored.
#### The 'overrideFeatureInstallOrder' property
diff --git a/docs/specs/devcontainer-reference.md b/docs/specs/devcontainer-reference.md
index 0944621a..20360b94 100644
--- a/docs/specs/devcontainer-reference.md
+++ b/docs/specs/devcontainer-reference.md
@@ -168,7 +168,7 @@ See [`workspaceMount` and `workspaceFolder`](devcontainerjson-reference.md#image
Users control the permissions of applications executed in the containers, allowing the developer to control them. The specification takes into account two types of user definitions:
* **Container User**: The user that will be used for all operations that run inside a container. This concept is native to containers. It may be set in the container image, using the `containerUser` property for **image** and **dockerfile** scenarios, or using an orchestratric specific property like `user` property in Docker Compose files.
-* **Remote User**: Used to run the [lifecycle](#lifecycle) scripts inside the container. This is also the user tools and editors that connect to the container should use to run their processes. This concept is not native to containers. Set using the `remoteEnv` property in all cases and defaults to the container user.
+* **Remote User**: Used to run the [lifecycle](#lifecycle) scripts inside the container. This is also the user tools and editors that connect to the container should use to run their processes. This concept is not native to containers. Set using the `remoteUser` property in all cases and defaults to the container user.
This separation allows the ENTRYPOINT for the image to execute with different permissions than the developer and allows for developers to switch users without recreating their containers.
From b3dde8484a3fafb23a7c9de73bafe578666c0177 Mon Sep 17 00:00:00 2001
From: Hossein Abbasi <16090309+hsnabszhdn@users.noreply.github.com>
Date: Sun, 6 Jul 2025 11:59:23 +1000
Subject: [PATCH 11/13] Uppercase the 'CONTRIBUTING' file
---
contributing.md => CONTRIBUTING.md | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename contributing.md => CONTRIBUTING.md (100%)
diff --git a/contributing.md b/CONTRIBUTING.md
similarity index 100%
rename from contributing.md
rename to CONTRIBUTING.md
From 583f98444fe552639c2a2f804bcf2db665fcf46b Mon Sep 17 00:00:00 2001
From: Johannes Mueller
Date: Sun, 15 Mar 2026 13:24:17 +0100
Subject: [PATCH 12/13] Add Emacs extension to supporting tools
Since early 2025 there is an extension for GNU Emacs under development to make
use of dev containers. Since its maturity is sufficient for everyday use, it
worth to be added to the page about supporting tools.
---
docs/specs/supporting-tools.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/docs/specs/supporting-tools.md b/docs/specs/supporting-tools.md
index 9db07b64..0b007515 100644
--- a/docs/specs/supporting-tools.md
+++ b/docs/specs/supporting-tools.md
@@ -38,6 +38,10 @@ Visual Studio added dev container support in Visual Studio 2022 17.4 for C++ pro
You may learn more in the [announcement blog post](https://devblogs.microsoft.com/cppblog/dev-containers-for-c-in-visual-studio/).
+### Emacs
+
+[GNU Emacs](https://www.gnu.org/software/emacs/) can make use of dev containers using the community extension [devcontainer.el](https://johannes-mueller.github.io/devcontainer.el/). The extension is available by the popular package registry [MELPA](https://melpa.org). It can also be installed directly from the source code that is available on [GitHub](https://github.com/johannes-mueller/devcontainer.el).
+
## Tools
### Dev Container CLI
From c95ffeed1d059abfe9ffbe79762dc2fa4e7c2421 Mon Sep 17 00:00:00 2001
From: Christof Marti
Date: Tue, 17 Mar 2026 10:06:02 +0100
Subject: [PATCH 13/13] Add tools from website
---
docs/specs/supporting-tools.md | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/docs/specs/supporting-tools.md b/docs/specs/supporting-tools.md
index 0b007515..a8f2f48b 100644
--- a/docs/specs/supporting-tools.md
+++ b/docs/specs/supporting-tools.md
@@ -38,6 +38,12 @@ Visual Studio added dev container support in Visual Studio 2022 17.4 for C++ pro
You may learn more in the [announcement blog post](https://devblogs.microsoft.com/cppblog/dev-containers-for-c-in-visual-studio/).
+### IntelliJ IDEA
+
+IntelliJ IDEA supports dev containers that can be run remotely via an SSH connection or locally using Docker.
+
+You may learn more in the [IntelliJ IDEA documentation](https://www.jetbrains.com/help/idea/connect-to-devcontainer.html).
+
### Emacs
[GNU Emacs](https://www.gnu.org/software/emacs/) can make use of dev containers using the community extension [devcontainer.el](https://johannes-mueller.github.io/devcontainer.el/). The extension is available by the popular package registry [MELPA](https://melpa.org). It can also be installed directly from the source code that is available on [GitHub](https://github.com/johannes-mueller/devcontainer.el).
@@ -56,9 +62,9 @@ VS Code has a [CLI](https://code.visualstudio.com/docs/remote/devcontainer-cli)
Cachix's [devenv](https://devenv.sh/) supports automatically generating a `.devcontainer.json` file so you can use it with any Dev Container Spec supporting tool. See [devenv documentation](https://devenv.sh/integrations/codespaces-devcontainer/) for detais.
-### Jetpack.io Devbox
+### Jetify Devbox
-[Jetpack.io's VS Code extension](https://marketplace.visualstudio.com/items?itemName=jetpack-io.devbox) supports a **Generate Dev Container files** command so you can use Jetpack.io from Dev Container Spec supporting tools.
+[Jetify](https://jetify.com) (formerly jetpack.io) is a [Nix](https://nixos.org/)-based service for deploying applications. [DevBox](https://www.jetify.com/devbox/) provides a way to use Nix to generate a development environment. [Jetify's VS Code extension](https://marketplace.visualstudio.com/items?itemName=jetpack-io.devbox) allows you to quickly take advantage of DevBox in any Dev Container Spec supporting tool or service.
### Visual Studio Code Dev Containers
@@ -150,3 +156,21 @@ Some properties may apply differently to codespaces.
| `${localEnv:VARIABLE_NAME}` | Any | For Codespaces, the host is in the cloud rather than your local machine.|
| `customizations.codespaces` | object | Codespaces reads this property from devcontainer.json, not image metadata. |
| `hostRequirements` | object | Codespaces reads this property from devcontainer.json, not image metadata. |
+
+### CodeSandbox
+
+[CodeSandbox](https://codesandbox.io/) provides cloud development environments running on a microVM architecture.
+
+When you import a GitHub repository into CodeSandbox, it will automatically provision a dedicated environment for every branch. Thanks to memory snapshotting, CodeSandbox then resumes and branches an environment in under two seconds.
+
+CodeSandbox offers support for multiple editors, so you can code using the CodeSandbox web editor, VS Code, or the CodeSandbox iOS app.
+
+### DevPod
+
+[DevPod](https://github.com/loft-sh/devpod) is a client-only tool to create reproducible developer environments based on a `devcontainer.json` on any backend. Each developer environment runs in a container and is specified through a `devcontainer.json`. Through DevPod providers these environments can be created on any backend, such as the local computer, a Kubernetes cluster, any reachable remote machine or in a VM in the cloud.
+
+### Ona (formerly Gitpod)
+
+[Ona](https://ona.com/) (formerly Gitpod) is the mission control for software projects and software engineering agents. It provides secure, ephemeral development environments that run in our cloud or your VPC, enabling humans and agents to collaborate seamlessly.
+
+For details on constraints, customization, and automation options, see the [Ona Dev Container docs](https://ona.com/docs/ona/configuration/devcontainer/overview).