The JSON reference page shows a table of properties in the devcontainer.json with a marker for fields that may be pulled from image metadata.
The merge logic page shows a table of properties, with additional columns indicating if it comes from devcontainer.json or "Feature metadata".
The metadata in image labels section shows how to store metadata and where to store it.
I think that the confusion is around understanding the difference between metadata config that comes from a devcontainer.json vs from a feature. There's no affordances in the labels to delineate. My hunch is that if you're implementing merge logic you should (mostly) ignore the "feature metadata" column on the merge logic table, and if you're implementing labeling you should honor the markers in the JSON reference general properties table, whether the value came from a devcontainer-feature.json or a devcontainer.json.
For a more specific example, let's look at the containerEnv property:
- Is not part of
devcontainer-feature.json
- Is part of
devcontainer.json
- Is marked as being valid in metadata
If you're building and tagging a devcontainer, you may take your entire merged configuration, filter out properties not marked as valid for metadata, and then store it as a new entry in the devcontainer.metadata image label list. In our specific case, the devcontainer.metadata entry would contain containerEnv.
Later, if you are building another devcontainer that uses this built image as a base, you would:
- Read in
devcontainer.json
- Read in all
devcontainer-feature.json
- Merge these two together
- Read in all
devcontainer.metadata entries
- Merge
devcontainer.metadata entries, in order, based on a mix of the general properties markers and the merge logic
That last bullet is the tricky part: containerEnv is marked in the merge logic page as something that only comes from devcontainer.json and not from feature metadata. But it was stored as metadata according to the spec. So it would be valid for the "merged config" to include the containerEnv that was stored as metadata, which contradicts the merge logic table.
Am I misunderstanding something fundamental here?
The JSON reference page shows a table of properties in the
devcontainer.jsonwith a marker for fields that may be pulled from image metadata.The merge logic page shows a table of properties, with additional columns indicating if it comes from
devcontainer.jsonor "Feature metadata".The metadata in image labels section shows how to store metadata and where to store it.
I think that the confusion is around understanding the difference between metadata config that comes from a
devcontainer.jsonvs from a feature. There's no affordances in the labels to delineate. My hunch is that if you're implementing merge logic you should (mostly) ignore the "feature metadata" column on the merge logic table, and if you're implementing labeling you should honor the markers in the JSON reference general properties table, whether the value came from adevcontainer-feature.jsonor adevcontainer.json.For a more specific example, let's look at the
containerEnvproperty:devcontainer-feature.jsondevcontainer.jsonIf you're building and tagging a devcontainer, you may take your entire merged configuration, filter out properties not marked as valid for metadata, and then store it as a new entry in the
devcontainer.metadataimage label list. In our specific case, thedevcontainer.metadataentry would containcontainerEnv.Later, if you are building another devcontainer that uses this built image as a base, you would:
devcontainer.jsondevcontainer-feature.jsondevcontainer.metadataentriesdevcontainer.metadataentries, in order, based on a mix of the general properties markers and the merge logicThat last bullet is the tricky part:
containerEnvis marked in the merge logic page as something that only comes fromdevcontainer.jsonand not from feature metadata. But it was stored as metadata according to the spec. So it would be valid for the "merged config" to include thecontainerEnvthat was stored as metadata, which contradicts the merge logic table.Am I misunderstanding something fundamental here?