Development Containers

  • Overview
  • Specification
  • Supporting Tools
  • Specification
  • Reference Implementation
  • devcontainer.json schema
  • devcontainer.json reference
  • Features
  • Features distribution
  • Contributing

Topics

Specification

Dev container Features contribution and discovery [proposal]

Note: This section provides information on a currently active proposal. See the Features distribution proposal in the spec repo for input and links to other proposed improvements.

This specification defines a pattern where community members and organizations can author and self-publish dev container ‘features’.

Goals include:

  • For community authors, a “self-served” mechanism for dev container feature publishing, either publicly or privately.
  • For users, the ability to validate the integrity of previously fetched assets.
  • For users, the ability for a user to pin to a particular version (absolute, or semantic version) of a feature to allow for consistent, repeatable environments.
  • The ability to standardize publishing such that supporting tools may implement mechanisms for feature discoverability.

Source Code

Features source code is stored in a git repository.

For ease of authorship and maintenance, [1..n] features can share a single git repository. This set of features is referred to as a collection, and will share the same devcontainer-collection.json file and ‘namespace’ (eg. <owner>/<repo>).

Source code for the set follows the example file structure below:

.
├── README.md
├── src
│   ├── dotnet
│   │   ├── devcontainer-feature.json
│   │   ├── install.sh
│   │   └── ...
|   ├
│   ├── go
│   │   ├── devcontainer-feature.json
│   │   └── install.sh
|   ├── ...
│   │   ├── devcontainer-feature.json
│   │   └── install.sh
├── test
│   ├── dotnet
│   │   ├── test.sh
│   │   └── ...
│   └── go
│   |   └── test.sh
|   ├── ...
│   │   └── test.sh
├── ...

Where src is a directory containing a sub-folder with the name of the feature (e.g. src/dotnet or src/go) with at least a file named devcontainer-feature.json that contains the feature metadata, and an install.sh script that implementing tools will use as the entrypoint to install the feature. Each sub-directory should be named such that it matches the id field of the devcontainer-feature.json. Other files can also be included in the feature’s sub-directory, and will be included during the packaging step alongside the two required files. Any files that are not part of the feature’s sub-directory (e.g. outside of src/dotnet) will not included in the packaging step.

Optionally, a mirrored test directory can be included with an accompanying test.sh script. Implementing tools may use this to run tests against the given feature.

Versioning

Each feature is individually versioned according to the semver specification. The version property in the respective devcontainer-feature.json file is parsed to determine if the feature should be republished.

Tooling that handles publishing features will not republish features if that exact version has already been published; however, tooling must republish major and minor versions in accordance with the semver specification.

Packaging

Features are distributed as tarballs. The tarball contains the entire contents of the feature sub-directory, including the devcontainer-feature.json, install.sh, and any other files in the directory.

The tarball is named devcontainer-feature-<id>.tgz, where <id> is the feature’s id field.

A reference implementation for packaging and distributing features is provided as a GitHub Action (https://github.com/devcontainers/action).

devcontainer-collection.json

The devcontainer-collection.json is an auto-generated metadata file.

Property Type Description
sourceInformation object Metadata from the implementing packaging tool.
features array The list of features that are contained in this collection.

Each features’s devcontainer-feature.json metadata file is appended into the features top-level array.

Distribution

There are several supported ways to distribute features. Distribution is handled by the implementing packaging tool.

A user references a distributed feature in a devcontainer.json as defined in ‘referencing a feature’.

OCI Registry

An OCI registry that implements the OCI Artifact Distribution Specification serves as the primary distribution mechanism for features.

Each packaged feature is pushed to the registry following the naming convention <registry>/<namespace>/<id>[:version], where version is the major, minor, and patch version of the feature, according to the semver specification.

The namespace is a unique indentifier for the collection of features. There are no strict rules for the namespace; however, one pattern is to set namespace equal to source repository’s <owner>/<repo>.

A custom media type application/vnd.devcontainers and application/vnd.devcontainers.layer.v1+tar are used as demonstrated below.

For example, the go feature in the devcontainers/features namespace at version 1.2.3 would be pushed to the ghcr.io OCI registry.

NOTE: The example below uses oras for demonstration purposes. A supporting tool should directly implement the required functionality from the aforementioned OCI artifact distribution specification.

# ghcr.io/devcontainers/features/go:1 
REGISTRY=ghcr.io
NAMESPACE=devcontainers/features
FEATURE=go

ARTIFACT_PATH=devcontainer-feature-go.tgz

for VERSION in 1  1.2  1.2.3  latest
do
    oras push ${REGISTRY}/${NAMESPACE}/${FEATURE}:${VERSION} \
            --manifest-config /dev/null:application/vnd.devcontainers \
                             ./${ARTIFACT_PATH}:application/vnd.devcontainers.layer.v1+tar
done

Namespace is the globally identifiable name for the collection of features. (eg: owner/repo for the source code’s git repository).

The auto-generated devcontainer-collection.json is pushed to the registry with the same namespace as above and no accompanying feature name. The collection file is always tagged as latest.

# ghcr.io/devcontainers/features
REGISTRY=ghcr.io
NAMESPACE=devcontainers/features

oras push ${REGISTRY}/${NAMESPACE}:latest \
        --manifest-config /dev/null:application/vnd.devcontainers \
                            ./devcontainer-collection.json:application/vnd.devcontainers.collection.layer.v1+json

Directly Reference Tarball

A feature can be referenced directly in a user’s devcontainer.json file by HTTPS URI that points to the tarball from the package step.

The .tgz archive file must be named devcontainer-feature-<featureId>.tgz.

Addendum: Locally Referenced

To aid in feature authorship, or in instances where a feature should not be published externally, individual features can be referenced locally from the project’s file tree.

A local feature is placed in a .devcontainer/ folder at the root of the project workspace folder and referenced in a user’s .devcontainer/devcontainer.json by relative path.

The relative path is provided using unix-style path syntax (eg ./<...>), regardless of the host operating system.

A local feature may not be referenced by absolute path, or by a path outside the .devcontainer/ folder.

The provided relative path is a path to the folder containing at least a devcontainer-feature.json and install.sh file, mirroring the structure previously outlined.

An example project is illustrated below:

.
├── .devcontainer/
│   ├── localFeatureA/
│   │   ├── devcontainer-feature.json
│   │   ├── install.sh
│   │   └── ...
│   ├── localFeatureB/
│   │   ├── devcontainer-feature.json
│   │   ├── install.sh
│   │   └── ...
│   ├── devcontainer.json
devcontainer.json
{
        // ...
        "features": {
                "./localFeatureA": {},
                "./localFeatureB": {}
        }
}
  • Hello from Seattle and Zürich.
  • Star
  • Watch
  • Manage cookies
  • Microsoft © 2022 Microsoft