Skip to content

Commit 1b7c38d

Browse files
committed
Add extends property for configuration inheritance
Document and schema-enable the extends keyword from #22, merging referenced files with the existing image metadata merge logic.
1 parent c95ffee commit 1b7c38d

3 files changed

Lines changed: 44 additions & 1 deletion

File tree

‎docs/specs/devcontainer-reference.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ To apply the metadata together with a user's `devcontainer.json` at runtime the
8484
| `updateRemoteUserUID` | `boolean` | Last value wins. | ✓ | |
8585
| `hostRequirements` | `cpus`, `memory`, `storage`, `gpu` | Max value wins. | ✓ | |
8686

87-
Variables in string values will be substituted at the time the value is applied. When the order matters, the `devcontainer.json` is considered last.
87+
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.
8888

8989
### Notes
9090

‎docs/specs/devcontainerjson-reference.md‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ 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). |
1213
| `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 `[]`. |
1314
| `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"}}` |
1415
| `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"}` |
@@ -29,6 +30,44 @@ Metadata properties marked with a 🏷️ can be stored in the `devcontainer.met
2930
| `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: <br />`"overrideFeatureInstallОrder": [ "ghcr.io/devcontainers/features/common-utils", "ghcr.io/devcontainers/features/github-cli" ]` |
3031
| `customizations` 🏷️| object | Product specific properties, defined in [supporting tools](supporting-tools.md) |
3132

33+
## Configuration inheritance
34+
35+
Multiple teams collaborating on a common codebase may need slightly different `devcontainer.json` settings. The `extends` property lets a configuration inherit from another JSON or JSONC file in the same repository:
36+
37+
```jsonc
38+
// .devcontainer/defaults.json
39+
{
40+
"name": "example/project",
41+
"forwardPorts": [80, 5432],
42+
"hostRequirements": {
43+
"storage": "64gb",
44+
"memory": "16gb"
45+
}
46+
}
47+
48+
// .devcontainer/devcontainer.json
49+
{
50+
"extends": "./defaults.json",
51+
"forwardPorts": [2222],
52+
"hostRequirements": {
53+
"memory": "32gb"
54+
},
55+
"onCreateCommand": ".devcontainer/on-create-command.sh"
56+
}
57+
```
58+
59+
`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.
60+
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+
63+
- Array properties such as `forwardPorts`, `capAdd`, and `securityOpt` are the union of values without duplicates.
64+
- `hostRequirements` takes the maximum of each field.
65+
- Object maps such as `remoteEnv`, `containerEnv`, `features`, and `customizations` merge per key, with the current file winning on conflicts.
66+
- Boolean `init` and `privileged` are `true` if at least one value is `true`.
67+
- Scalar properties such as `name`, `image`, `remoteUser`, and lifecycle commands use last value wins.
68+
69+
The `extends` property itself is not present in the merged result.
70+
3271
## Scenario specific properties
3372

3473
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.

‎schemas/devContainer.base.schema.json‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
"type": "string",
1717
"description": "A name for the dev container which can be displayed to the user."
1818
},
19+
"extends": {
20+
"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."
22+
},
1923
"features": {
2024
"type": "object",
2125
"description": "Features to add to the dev container.",

0 commit comments

Comments
 (0)