Skip to content

Commit

Permalink
Merge pull request #27 from edgonmsft/edgonmsft/features2-proposal
Browse files Browse the repository at this point in the history
Proposal for Features functionality and spec.
  • Loading branch information
edgonmsft authored May 25, 2022
2 parents b1e8184 + b0357e2 commit 953761c
Showing 1 changed file with 145 additions and 0 deletions.
145 changes: 145 additions & 0 deletions proposals/devcontainer-features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Dev container features reference

Dev container features provide a smooth path for customizing your container definitions. Features are self contained units of code meant to facilitate creation of custom images for application or development containers.

From a practical point of view, features are folders that contain units of code with different entrypoints for different lifecycle events.

Features can be defined by a `devcontainer-feature.json` file in the root folder of the feature. The file is optional for backwards compatibility but it is required for any new features being authored.

Features are to be executed in sequence as defined in `devcontainer.json`.

## Folder Structure

A feature is a self contained entity in a folder. A feature release would be a tar file that contains all files part of the feature.

```
+-- feature
| +-- devcontainer-feature.json
| +-- install.sh (default)
| +-- (other files)
```

In case `devcontainer-feature.json` does not include a reference for the lifecycle scripts the application will look for the default script names and will execute them if available.

In case there is intent to create a set of features that share code, it is possible to create a feature collection in the following way:

```
collectionFolder
+-- devcontainer-collection.json
+-- common (or similar)
| +-- (library files)
+-- feature1
| +-- devcontainer-feature.json
| +-- install.sh
| +-- (other files)
+-- feature2
(etc)
```


## devcontainer-feature.json properties

the `devcontainer-feature.json` file defines information about the feature to be used by any supporting tools and the way the feature will be executed.

The properties of the file are as follows:

| Property | Type | Description |
| :--- | :--- | :--- |
| id | string | Id of the feature/definition. The id should be unique in the context of the repository/published package where the feature exists. |
| name | string | Name of the feature/definition. |
| description | string | Description of the feature/definition. |
| documentationURL | string | Url that points to the documentation of the feature. |
| licenseURL | string | Url that points to the license of the feature. |
| version | string | Version of the feature. |
| keywords | array | List of keywords relevant to a user that would search for this definition/feature. |
| install.app | string | App to execute.|
| install.file | string | Parameters/script to execute (defaults to install.sh).|
| options | object | Possible options to be passed as environment variables to the execution of the scripts |
| containerEnv | object | A set of name value pairs that sets or overrides environment variables. |
| privileged | boolean | If priveleged mode is required by the feature. |
| init | boolean | If it's necesarry to run `init`. |
| capAdd | array | Additional capabilities needed by the feature. |
| securityOpt | array | Security options needed by the feature. |
| entrypoint | string | Set if the feature requires an entrypoint. |

Options

| Property | Type | Description |
| :--- | :--- | :--- |
| id | string | Id of the option. |
| id.type | string | Type of the option. |
| id.enum | string array | Possible values. |
| id.default | string | Default value for the option. |
| id.description | string | Description for the option. |

## devcontainer-collection.json properties

A feature collection file is a compilation of the `devcontainer-feature.json` files for each individual feature. It inlines all the information in each `devcontainer-feature.json` for each feature.

If the application finds a `devcontainer-collection.json` file in the root of a downloaded tar file, then it uses that file to find the particular feature that will be executed.

In addition to the list of features included, the file includes the following properties.

| Property | Type | Description |
| :--- | :--- | :--- |
| name | string | Name of the collection. |
| reference | string | Reference information of the repository and path where the code is stored. |
| version | string | Version of the code. |

In most cases, the `devcontainer-collection.json` file can be generated automatically at the moment of creating a release.

## devcontainer.json properties

Features are referenced in `devcontainer.json` , where the `features` tag consists of an array with the ordered list of features to be included in the container image.

The properties are:
| Property | Type | Description |
| :--- | :--- | :--- |
| id | string | Reference to the particular feature to be included. |
| options | object | Type of the option .|

The `id` is the main reference point for how to find and download a particular feature. `id` can be defined in any of the following ways:

| Type | Description |
| :--- | :--- |
| feature | A simple name referencing a feature; it's included with the application used to execute `devcontainer.json`.|
| organization/repository/{feature or collectionl/feature}/@version | Reference to a particular release in a repository. |
| https://<../URI/..>/devcontainer-features.tgz#{optional feature} | Direct reference to a file download. |
| ./{local-path} -or- ../{local-path} | A path relative to devcontainer.json where a feature or feature collection can be found. |

## Authoring

Features can be authored in a number of languages, the most straightforward being bash scripts. If a feature is authored in a different language information about it should be included in the metadata so that users can make an informed choice about it.

Reference information about the application required to execute the feature should be included in `devcontainer-feature.json` in the metadata section.

Applications should default to `/bin/sh` for features that do not include this information.

If the feature is included in a folder as part of the repository that contains `devcontainer.json`, no other steps are necessary.

## Release

A release is created when the objective is to have other users use a feature.

A release consists of the following:

1.- Tar file with all the included files for the feature or feature collection.
2.- A copy of the `devcontainer-feature.json` or `devcontainer-collection.json` file that defines the contents of the tar file, with additional information added to validate it.

| Property | Type | Description |
| :--- | :--- | :--- |
| version | string | SemVer version of the release. |
| checksum | string | Checksum of the tar file. |

## Execution

There are several things to keep in mind for an application that implements features:

- Features are executed in the order defined in devcontainer.json
- It should be possible to execute a feature multiple times with different parameters.
- Features are used to create an image that can be used to create a container or not.
- Parameters like `privileged`, `init` are included if just 1 feature requires them.
- Parameters like `capAdd`, `securityOp` are concatenated.
- ContainerEnv is added before the feature is executed as `ENV` commands in the docker file.
- Features are added to an image in two passes. One for `aquire` scripts and another for `install` scripts.
- Each script executes as its own layer to aid in caching and rebuilding.

0 comments on commit 953761c

Please sign in to comment.