From 1b7c38d6ffc6218f635be6ba4aaf4249a1a103ea Mon Sep 17 00:00:00 2001 From: Samuel Frost Date: Fri, 18 Sep 2026 17:43:39 +0000 Subject: [PATCH] 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. --- docs/specs/devcontainer-reference.md | 2 +- docs/specs/devcontainerjson-reference.md | 39 ++++++++++++++++++++++++ schemas/devContainer.base.schema.json | 4 +++ 3 files changed, 44 insertions(+), 1 deletion(-) 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..60954097 100644 --- a/docs/specs/devcontainerjson-reference.md +++ b/docs/specs/devcontainerjson-reference.md @@ -9,6 +9,7 @@ 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 | 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). | | `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 +30,44 @@ 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 + +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: + +```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 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. + +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: + +- 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`. +- Scalar properties such as `name`, `image`, `remoteUser`, and lifecycle commands use last value wins. + +The `extends` property itself is not present in the merged result. + ## 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..13cc7730 100644 --- a/schemas/devContainer.base.schema.json +++ b/schemas/devContainer.base.schema.json @@ -16,6 +16,10 @@ "type": "string", "description": "A name for the dev container which can be displayed to the user." }, + "extends": { + "type": "string", + "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." + }, "features": { "type": "object", "description": "Features to add to the dev container.",