### Example of tool-specific properties in "customizations" Source: https://github.com/devcontainers/spec/blob/main/CONTRIBUTING.md Shows the structure for tool-specific properties under the "customizations" property, with a "vscode" namespace example. Use this format when proposing new tool-specific namespaces or properties. ```jsonc // Configure tool-specific properties. "customizations": { // Configure properties specific to VS Code. "vscode": { // Set *default* container specific settings.json values on container create. "settings": {}, // Additional VS Code specific properties... } }, ``` -------------------------------- ### install.sh to copy bundled script Source: https://github.com/devcontainers/spec/blob/main/docs/specs/features-contribute-lifecycle-scripts.md Example install.sh script that moves a bundled script to /usr/myDir so it persists outside /tmp. The ellipses indicate additional steps not shown. ```shell #!/bin/sh cp ./bundleScript /usr/myDir ... ... ``` -------------------------------- ### FeatureB file structure Source: https://github.com/devcontainers/spec/blob/main/docs/specs/features-contribute-lifecycle-scripts.md Example file structure for featureB showing the bundled script, devcontainer-feature.json, and install.sh under src/featureB. ```text . ├── src │ ├── featureB │ │ ├── bundledScript.sh │ │ ├── devcontainer-feature.json │ │ └── install.sh ``` -------------------------------- ### Example project directory structure for local Features Source: https://github.com/devcontainers/spec/blob/main/docs/specs/devcontainer-features-distribution.md Shows the required layout: a .devcontainer folder at the project root, with each local Feature in a sub-folder named after its id, containing at least devcontainer-feature.json and install.sh. ```text . ├── .devcontainer/ │ ├── localFeatureA/ │ │ ├── devcontainer-feature.json │ │ ├── install.sh │ │ └── ... │ ├── localFeatureB/ │ │ ├── devcontainer-feature.json │ │ ├── install.sh │ │ └── ... │ ├── devcontainer.json ``` -------------------------------- ### devcontainer-lock.json example with OCI and tarball features Source: https://github.com/devcontainers/spec/blob/main/docs/specs/devcontainer-lockfile.md Example lockfile showing two features: an OCI feature from ghcr.io and a tarball feature from a custom domain. Each entry records the version, resolved identifier (with sha256 for OCI), and integrity checksum. ```jsonc { "features": { "ghcr.io/devcontainers/features/node:1": { "version": "1.0.4", "resolved": "ghcr.io/devcontainers/features/node@sha256:567d704b3f4d3eca3acee51ded7c460a8395436d135d53d1175fb565daff42b8", "integrity": "sha256:567d704b3f4d3eca3acee51ded7c460a8395436d135d53d1175fb565daff42b8" }, "https://mycustomdomain.com/devcontainer-feature-myfeature.tgz": { "version": "1.2.3", "resolved": "https://mycustomdomain.com/devcontainer-feature-myfeature.tgz", "integrity": "sha256:567d704b3f4d3eca3acee51ded7c460a8395436d135d53d1175fb565daff42b8" } } } ``` -------------------------------- ### Example of the optionalPaths property in devcontainer-template.json Source: https://github.com/devcontainers/spec/blob/main/docs/specs/devcontainer-templates.md Shows how to specify optional files and directories. Single files use full relative paths; directories use a trailing /* to include all recursive contents. ```jsonc { "id": "cpp", "version": "3.0.0", "name": "C++", "description": "Develop C++ applications", "optionalPaths": [ "GETTING-STARTED.md", // Single file "example-project-1/MyProject.csproj", // Single file in nested directory ".github/*" // Entire recursive contents of directory ] } ``` -------------------------------- ### Example features object in devcontainer.json Source: https://github.com/devcontainers/spec/blob/main/docs/specs/devcontainer-features.md Shows a valid `features` object with various feature references and options. The `:latest` version is implicit if omitted. Options can be strings or booleans. ```jsonc "features": { "ghcr.io/user/repo/go": {}, "ghcr.io/user/repo1/go:1": {}, "ghcr.io/user/repo2/go:latest": {}, "https://github.com/user/repo/releases/devcontainer-feature-go.tgz": { "optionA": "value" }, "./myGoFeature": { "optionA": true, "optionB": "hello", "version" : "1.0.0" } } ``` -------------------------------- ### Example of the options property in devcontainer-feature.json Source: https://github.com/devcontainers/spec/blob/main/docs/specs/devcontainer-features.md Shows the structure of the options property with an option ID, type, description, proposals, and default value. The option ID becomes an all-caps environment variable. ```json { "options": { "optionIdGoesHere": { "type": "string", "description": "Description of the option", "proposals": ["value1", "value2"], "default": "value1" } } } ``` -------------------------------- ### devcontainer.json with features and lifecycle hooks Source: https://github.com/devcontainers/spec/blob/main/docs/specs/features-contribute-lifecycle-scripts.md Example devcontainer.json that uses featureA and featureB and defines user-level postCreateCommand and postAttachCommand. The postAttachCommand uses parallel syntax with server and db commands. ```jsonc { "image": "ubuntu", "features": { "featureA": {}, "featureB": {}, }, "postCreateCommand": "userPostCreate.sh", "postAttachCommand": { "server": "npm start", "db": ["mysql", "-u", "root", "-p", "my database"] }, } ``` -------------------------------- ### install.sh entrypoint script using option environment variables Source: https://github.com/devcontainers/spec/blob/main/docs/specs/devcontainer-features.md The install.sh entrypoint script that sources the emitted environment variables and prints their values. ```bash #!/usr/bin/env bash echo "Version is $VERSION" echo "Pip? $PIP" echo "Optimize? $OPTIMIZE" ``` -------------------------------- ### roundPriority assignments for overrideFeatureInstallOrder Source: https://github.com/devcontainers/spec/blob/main/docs/specs/feature-dependencies.md Resulting roundPriority assignments for the overrideFeatureInstallOrder example, where each Feature gets a priority of n - idx. ```json const roundPriority = { "foo": 3, "bar": 2, "baz": 1 } ``` -------------------------------- ### devcontainer-feature.json with dependsOn property Source: https://github.com/devcontainers/spec/blob/main/docs/specs/feature-dependencies.md Example devcontainer-feature.json showing the dependsOn property with four published Feature dependencies, including version tags and a digest pin. The orchestrating tool installs the dependencies before the declaring Feature. ```json { "name": "My Feature", "id": "myFeature", "version": "1.0.0", "dependsOn": { "ghcr.io/second:1": { "flag": true }, "features.azurecr.io/third:1": {}, "features.azurecr.io/fourth:1.2.3": {}, "features.azurecr.io/fifth@sha256:a4cdc44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855": {} } } ``` -------------------------------- ### overrideFeatureInstallOrder example Source: https://github.com/devcontainers/spec/blob/main/docs/specs/feature-dependencies.md Example of the overrideFeatureInstallOrder property in devcontainer.json, listing Feature IDs in descending priority order. ```json overrideFeatureInstallOrder = [ "foo", "bar", "baz" ] ``` -------------------------------- ### devcontainer-lock.json example with dependsOn dependency Source: https://github.com/devcontainers/spec/blob/main/docs/specs/devcontainer-lockfile.md Example lockfile where a feature has a dependency. The dependsOn array lists the dependent feature identifier, and the lockfile includes a separate record for that dependency. ```jsonc { "features": { "ghcr.io/codspace/dependson/a": { "version": "1.2.1", "resolved": "ghcr.io/codspace/dependson/a@sha256:932027ef71da186210e6ceb3294c3459caaf6b548d2b547d5d26be3fc4b2264a", "integrity": "sha256:932027ef71da186210e6ceb3294c3459caaf6b548d2b547d5d26be3fc4b2264a", "dependsOn": [ "ghcr.io/codspace/dependson/e:2" ] }, "ghcr.io/codspace/dependson/e:2": { "version": "2.3.4", "resolved": "ghcr.io/codspace/dependson/e@sha256:9f36f159c70f8bebff57f341904b030733adb17ef12a5d58d4b3d89b2a6c7d5a", "integrity": "sha256:9f36f159c70f8bebff57f341904b030733adb17ef12a5d58d4b3d89b2a6c7d5a" } } } ``` -------------------------------- ### Make install.sh executable and run it Source: https://github.com/devcontainers/spec/blob/main/docs/specs/devcontainer-features.md Set the execute bit on install.sh and invoke it directly to ensure the appropriate shell is used. Recommended for Feature authors to write install.sh using a shell available by default in supported distributions. ```bash chmod +x install.sh && ./install.sh ``` -------------------------------- ### Output of install.sh with python Feature options Source: https://github.com/devcontainers/spec/blob/main/docs/specs/devcontainer-features.md The output produced by the install.sh script when run with the emitted environment variables. ```text Version is 3.10 Pip? false Optimize? true ``` -------------------------------- ### Feature with bundled script lifecycle hook Source: https://github.com/devcontainers/spec/blob/main/docs/specs/features-contribute-lifecycle-scripts.md Example devcontainer-feature.json for featureB that contributes a postCreateCommand pointing to a script bundled with the feature. It also specifies installsAfter featureA. ```jsonc { "id": "featureB", "version": "1.0.0", "postCreateCommand": "/usr/myDir/bundledScript.sh", "installsAfter": [ "featureA" ] } ``` -------------------------------- ### Switch user context with su Source: https://github.com/devcontainers/spec/blob/main/docs/specs/devcontainer-features.md Switch to another user's context from the install.sh script, which runs as root during a container image build. This allows non-root image modifications even if sudo is not present in the base image. ```bash su ${USERNAME} -c "command-goes-here" ```