DevContainer/Feature/Concept/Docker Build Order
Properties
DevContainer Features and Docker Layer Caching Conceptual Overview
Overview
- DevContainer Features are modular components that enhance development environments by adding specific tools, runtimes, or configurations to base container images.
- Understanding how Features map to Docker layers and interact with Docker's caching mechanism is crucial for optimizing build performance and development workflow efficiency.
Context
- Docker images are constructed in layers, with each instruction creating a new layer that can be cached for faster subsequent builds.
- DevContainer Features were designed to provide reusable, modular enhancements that can be applied to various base images.
- The challenge arises when Features interact with Docker's layer caching, as changes can invalidate cache layers and slow down rebuilds.
Key Principles
- Layer-Based Architecture: Each DevContainer Feature creates additional Docker layers on top of the base image.
"Features are designed to install atop a wide-range of base container images." GitHub
- Sequential Application: Features are applied in an order determined by the implementing tool, creating a layered build process.
"By default, Features are installed on top of a base image in an order determined as optimal by the implementing tool." Visual Studio Code
- Cache Dependency: Changes to any layer invalidate that layer and all subsequent layers, affecting build performance.
"rebuilding is something very common … the new feature added may not be the last feature in that order - and break the container build cache of many features needlessly." GitHub
- Modular Design: Features are self-contained entities with
devcontainer-feature.jsonmetadata andinstall.shscripts."A Feature is a self contained entity in a folder with at least a
devcontainer-feature.jsonandinstall.shentrypoint script." containers.dev
- Layer-Based Architecture: Each DevContainer Feature creates additional Docker layers on top of the base image.
Mechanism
- The DevContainer CLI builds your project's Dockerfile (or pulls your specified image) first, creating the base image.
- The devcontainer tooling/CLI implements that by producing a temporary Dockerfile (often shown in logs as
Dockerfile-with-features) that startsFROM <your-built-or-pulled-image>and then runs featureinstall.shsteps, creating additional image layers on top. That is why the CLI builds your Dockerfile (or pulls yourimage) first, then applies features. Visual Studio Code+1
- The devcontainer tooling/CLI implements that by producing a temporary Dockerfile (often shown in logs as
- Features are then applied by generating a temporary
Dockerfile-with-featuresthat startsFROM <your-built-or-pulled-image>."Within these folders there is a Docker-with-features Dockerfile which is used to build a container, as it can be seen in the logs above." GitHub
- Each Feature's
install.shscript executes as DockerRUNinstructions, creating additional layers on top of the base image.- The spec requires features to be install scripts + metadata and says they are applied on top of a base image. containers.dev+1
- The resulting image contains all base image layers plus the Feature layers in the determined order.
- Because of that flow, changes to your project's Dockerfile or to the feature list/order can invalidate caches and cause longer rebuilds — this is a documented/observed pain point in the community. GitHub
- The DevContainer CLI builds your project's Dockerfile (or pulls your specified image) first, creating the base image.
Implementation Details
- Dockerfile Layer Generation: The DevContainer CLI uses
getFeatureLayers()function to generate Dockerfile instructions for feature installation, creating individual layers for each feature.- The system transforms user-declared features from
devcontainer.jsoninto executable Dockerfile layers through a multi-stage pipeline, supporting both traditional COPY instructions and BuildKit mount contexts for improved build performance. DeepWiki
- The system transforms user-declared features from
- Feature Installation Wrapper: Each feature gets wrapped in an installation script generated by
getFeatureInstallWrapperScript()that provides error handling, metadata display, environment variable sourcing, and installation execution.- The wrapper script ensures consistent feature installation behavior and provides troubleshooting capabilities during the Docker build process. DeepWiki
- Layer Processing Pipeline: The feature configuration system processes features through multiple stages: parsing declarations, identifying sources, fetching content, and generating Dockerfile layers.
- This multi-stage pipeline ensures that each feature becomes a distinct Docker layer, allowing for granular caching and build optimization. DeepWiki
- Dockerfile Layer Generation: The DevContainer CLI uses
Examples
- Base Image + Features Flow:
- Cache Invalidation Scenario:
- Migration from Dockerfile to Features:
- Developers can migrate from maintaining custom Dockerfiles to using predefined Features in
devcontainer.json, simplifying environment setup and reducing maintenance overhead. - Features allow developers to add predefined scripts to their
devcontainer.jsonfile, eliminating the need to maintain custom Dockerfiles while ensuring consistent configurations across multiple projects. Person/Aaron Powell - "Simplifying devcontainers With Features"
- Developers can migrate from maintaining custom Dockerfiles to using predefined Features in
Misconceptions
- Features are just configuration → False. Features create actual Docker layers through executable installation scripts.
- Feature order doesn't matter → False. Order affects caching efficiency and build performance.
- All features rebuild when one changes → False. Only changed features and subsequent ones rebuild due to layer invalidation.
- Features are applied to the final image → False. Features are applied during the build process, creating intermediate layers.
Related