diff --git a/docs/specs/devcontainer-reference.md b/docs/specs/devcontainer-reference.md
index aa269340..b160706e 100644
--- a/docs/specs/devcontainer-reference.md
+++ b/docs/specs/devcontainer-reference.md
@@ -84,7 +84,7 @@ To apply the metadata together with a user's `devcontainer.json` at runtime the
| `updateRemoteUserUID` | `boolean` | Last value wins. | ✓ | |
| `hostRequirements` | `cpus`, `memory`, `storage`, `gpu` | Max value wins. | ✓ | |
-Variables in string values will be substituted at the time the value is applied. When the order matters, the `devcontainer.json` is considered last.
+Variables in string values will be substituted at the time the value is applied. When the order matters, the `devcontainer.json` is considered last. The same merge logic is used when a `devcontainer.json` file [extends](devcontainerjson-reference.md#configuration-inheritance) another configuration file in the same repository.
### Notes
diff --git a/docs/specs/devcontainerjson-reference.md b/docs/specs/devcontainerjson-reference.md
index fa3893b1..0bea315f 100644
--- a/docs/specs/devcontainerjson-reference.md
+++ b/docs/specs/devcontainerjson-reference.md
@@ -9,6 +9,8 @@ Metadata properties marked with a 🏷️ can be stored in the `devcontainer.met
| Property | Type | Description |
|----------|------|-------------|
| `name` | string | A name for the dev container displayed in the UI |
+| `extends` | string | Relative path to a JSON or JSONC base configuration in the same repository. See [Configuration inheritance](#configuration-inheritance). |
+| `extendsMergeMode` | string | Optional. `combine` (default) or `override`. See [Configuration inheritance](#configuration-inheritance). |
| `forwardPorts` 🏷️ | array | An array of port numbers or `"host:port"` values (e.g. `[3000, "db:5432"]`) that should always be forwarded from inside the primary container to the local machine (including on the web). The property is most useful for forwarding ports that cannot be auto-forwarded because the related process that starts before the `devcontainer.json` supporting service / tool connects or for forwarding a service not in the primary container in Docker Compose scenarios (e.g. `"db:5432"`). Defaults to `[]`. |
| `portsAttributes` 🏷️ | object | Object that maps a port number, `"host:port"` value, range, or regular expression to a set of default options. See [port attributes](#port-attributes) for available options. For example:
`"portsAttributes": {"3000": {"label": "Application port"}}` |
| `otherPortsAttributes` 🏷️ | object | Default options for ports, port ranges, and hosts that aren't configured using `portsAttributes`. See [port attributes](#port-attributes) for available options. For example:
`"otherPortsAttributes": {"onAutoForward": "silent"}` |
@@ -29,6 +31,55 @@ Metadata properties marked with a 🏷️ can be stored in the `devcontainer.met
| `overrideFeatureInstallOrder` | array | By default, Features will attempt to automatically set the order they are installed based on a `installsAfter` property within each of them. This property allows you to override the Feature install order when needed. For example:
`"overrideFeatureInstallОrder": [ "ghcr.io/devcontainers/features/common-utils", "ghcr.io/devcontainers/features/github-cli" ]` |
| `customizations` 🏷️| object | Product specific properties, defined in [supporting tools](supporting-tools.md) |
+## Configuration inheritance
+
+Use `extends` to inherit settings from another JSON or JSONC file in the same repository:
+
+```jsonc
+// .devcontainer/defaults.json
+{
+ "name": "example/project",
+ "forwardPorts": [80, 5432],
+ "hostRequirements": {
+ "storage": "64gb",
+ "memory": "16gb"
+ }
+}
+
+// .devcontainer/devcontainer.json
+{
+ "extends": "./defaults.json",
+ "forwardPorts": [2222],
+ "hostRequirements": {
+ "memory": "32gb"
+ },
+ "onCreateCommand": ".devcontainer/on-create-command.sh"
+}
+```
+
+`extends` is relative to the file that declares it, for example `"./defaults.json"`, `"../defaults.json"`, or `"./dev/defaults.json"`. Referenced files may also use `extends`. Absolute paths and URLs are not supported.
+
+The referenced configuration is merged first, then the current file is applied. Use `extendsMergeMode` on the file that declares `extends` to choose the merge behavior.
+
+Both `extends` and `extendsMergeMode` properties are removed from the merged result.
+
+### `extendsMergeMode`: `combine` (default)
+
+Uses the same [merge logic](devcontainer-reference.md#merge-logic) as image metadata:
+
+- Array properties such as `forwardPorts`, `capAdd`, and `securityOpt` are the union of values without duplicates.
+- `hostRequirements` takes the maximum of each field.
+- Object maps such as `remoteEnv`, `containerEnv`, `features`, and `customizations` merge per key, with the current file winning on conflicts.
+- Boolean `init` and `privileged` are `true` if at least one value is `true`.
+- Single-value properties such as `name`, `image`, and `remoteUser` override the value from the referenced file if set in the current file.
+
+### `extendsMergeMode`: `override`
+
+Uses top-level merging with key-based overrides (`{ ...base, ...current }`):
+
+- Properties set in the current file replace the inherited value.
+- Properties omitted from the current file keep the inherited value.
+
## Scenario specific properties
The focus of `devcontainer.json` is to describe how to enrich a container for the purposes of development rather than acting as a multi-container orchestrator format. Instead, container orchestrator formats can be referenced when needed to manage multiple containers and their lifecycles. Today, `devcontainer.json` includes scenario specific properties for working without a container orchestrator (by directly referencing an image or Dockerfile) and for using Docker Compose as a simple multi-container orchestrator.
diff --git a/schemas/devContainer.base.schema.json b/schemas/devContainer.base.schema.json
index 86709eca..f1da9ebe 100644
--- a/schemas/devContainer.base.schema.json
+++ b/schemas/devContainer.base.schema.json
@@ -16,6 +16,18 @@
"type": "string",
"description": "A name for the dev container which can be displayed to the user."
},
+ "extends": {
+ "type": "string",
+ "description": "Relative path to a JSON or JSONC configuration to be inherited from present in the same repository."
+ },
+ "extendsMergeMode": {
+ "type": "string",
+ "enum": [
+ "combine",
+ "override"
+ ],
+ "description": "Specifies how to merge this file with the referenced extends file when extends is set. combine (default) uses image metadata merge logic. override inherits then replaces top-level properties when a key is set in this file."
+ },
"features": {
"type": "object",
"description": "Features to add to the dev container.",