Skip to content

Commit 9f8d6d7

Browse files
committed
Document extendsMergeMode for configuration inheritance
Schema and reference docs for combine (default) and override merge when using extends, aligned with the Dev Container CLI behavior.
1 parent 1b7c38d commit 9f8d6d7

2 files changed

Lines changed: 25 additions & 4 deletions

File tree

‎docs/specs/devcontainerjson-reference.md‎

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ Metadata properties marked with a 🏷️ can be stored in the `devcontainer.met
99
| Property | Type | Description |
1010
|----------|------|-------------|
1111
| `name` | string | A name for the dev container displayed in the UI |
12-
| `extends` | string | A relative path to a JSON or JSONC file in the same repository to use as a base configuration. The referenced file is merged with this file using the [image metadata merge logic](devcontainer-reference.md#merge-logic). See [Configuration inheritance](#configuration-inheritance). |
12+
| `extends` | string | A relative path to a JSON or JSONC file in the same repository to use as a base configuration. The referenced file is merged with this file using the logic selected by `extendsMergeMode`. See [Configuration inheritance](#configuration-inheritance). |
13+
| `extendsMergeMode` | string | Optional. `combine` (default) or `override`. See [Configuration inheritance](#configuration-inheritance). |
1314
| `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 `[]`. |
1415
| `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: <br />`"portsAttributes": {"3000": {"label": "Application port"}}` |
1516
| `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: <br /> `"otherPortsAttributes": {"onAutoForward": "silent"}` |
@@ -58,15 +59,27 @@ Multiple teams collaborating on a common codebase may need slightly different `d
5859

5960
`extends` is a path relative to the file that declares it (for example `"./defaults.json"`, `"../defaults.json"`, or `"./dev/defaults.json"`). Referenced files may themselves use `extends`. Absolute paths and URLs are not supported.
6061

61-
The referenced configuration is merged with the current file using the same [merge logic](devcontainer-reference.md#merge-logic) applied to image metadata, with the current file considered last:
62+
The referenced configuration is merged with the current file. The current file is considered last. Use `extendsMergeMode` on the file that declares `extends` to choose the merge behavior (default: `combine`).
63+
64+
### `extendsMergeMode`: `combine` (default)
65+
66+
Uses the same [merge logic](devcontainer-reference.md#merge-logic) applied to image metadata:
6267

6368
- Array properties such as `forwardPorts`, `capAdd`, and `securityOpt` are the union of values without duplicates.
6469
- `hostRequirements` takes the maximum of each field.
6570
- Object maps such as `remoteEnv`, `containerEnv`, `features`, and `customizations` merge per key, with the current file winning on conflicts.
6671
- Boolean `init` and `privileged` are `true` if at least one value is `true`.
6772
- Scalar properties such as `name`, `image`, `remoteUser`, and lifecycle commands use last value wins.
6873

69-
The `extends` property itself is not present in the merged result.
74+
### `extendsMergeMode`: `override`
75+
76+
Uses overlay-style merging when the current file should replace rather than combine with the base:
77+
78+
- Arrays and scalars from the current file replace the base when set on the current file (for example, `forwardPorts` is only the current file's list).
79+
- Object maps and `hostRequirements` are shallow-merged per key, with the current file winning on conflicts.
80+
- Boolean `init` and `privileged` use the current file's value when set.
81+
82+
Neither `extends` nor `extendsMergeMode` is present in the merged result.
7083

7184
## Scenario specific properties
7285

‎schemas/devContainer.base.schema.json‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,15 @@
1818
},
1919
"extends": {
2020
"type": "string",
21-
"description": "A relative path to a JSON or JSONC file in the same repository whose configuration is used as a base. The referenced file is merged with this file using the image metadata merge logic."
21+
"description": "A relative path to a JSON or JSONC file in the same repository whose configuration is used as a base. The referenced file is merged with this file using the merge logic selected by extendsMergeMode."
22+
},
23+
"extendsMergeMode": {
24+
"type": "string",
25+
"enum": [
26+
"combine",
27+
"override"
28+
],
29+
"description": "How to merge the referenced extends file with this file. combine (default) uses the image metadata merge logic. override replaces arrays and scalars from this file and shallow-merges object maps and hostRequirements."
2230
},
2331
"features": {
2432
"type": "object",

0 commit comments

Comments
 (0)