Preinstalling Extensions in a Prebuilt DevContainer Image
Even with a cache volume, the first attach downloads extensions. This page bakes them into a prebuilt server image, so a fresh container attaches with extensions already present — the fastest possible editor startup, especially for Codespaces prebuilds.
Prerequisites
You need a prebuild pipeline and the extension list to bake.
- A way to build and publish a prebuilt image (CI or Codespaces prebuild).
- The pinned extension IDs to preinstall.
- The VS Code server available in the build.
Step-by-Step Implementation
- Declare pinned extensions.
{ "customizations": { "vscode": { "extensions": ["dbaeumer.vscode-eslint@3.0.10"] } }, "remoteUser": "vscode" }
- Preinstall them in the prebuild (Codespaces prebuilds do this automatically from the config).
# In a prebuild image, install extensions into the server ahead of time
RUN code-server --install-extension dbaeumer.vscode-eslint || true
-
Publish the prebuilt image and reference it.
-
Attach and confirm extensions are already present.
ls ~/.vscode-server/extensions | grep eslint
Common Pitfalls
Prebuild issues are unpinned extensions or a prebuild that doesn't cover the config.
| Symptom | Root Cause | Remediation |
|---|---|---|
| First attach still downloads extensions | Not baked into the image | Preinstall in the prebuild |
| Prebuilt extensions drift | Unpinned versions | Pin exact extension versions |
| Prebuild stale after adding an extension | Not rebuilt on config change | Trigger prebuild on config change |
| Image bloated | Too many extensions baked | Bake only the essentials |
Conclusion
A prebuilt image with extensions baked in is the fastest editor startup there is: a fresh container attaches with everything already installed. Pin the versions and rebuild the prebuild when the extension list changes, and even the first attach is near-instant.
FAQ
How is this different from a cache volume? A cache volume speeds rebuilds by reusing downloaded extensions, but the very first attach on a fresh machine still downloads them. A prebuilt image bakes the extensions into the image itself, so even the first attach has them present — the extra step beyond caching.
Do Codespaces prebuilds handle this automatically? Yes — a Codespaces prebuild builds from your config and bakes the declared extensions into the prebuilt image, so creating a Codespace from a prebuilt branch attaches with extensions ready. Locally, you bake them into a prebuilt image yourself.
Should I still pin extension versions when prebuilding? Absolutely. Pinning keeps the prebuilt image reproducible and prevents an auto-update from changing behaviour. Rebuild the prebuild when you bump a version, so the baked extensions stay in lockstep with your pinned config.
Related
- Up to Managing VS Code Extension Caches — the caching overview.
- Pinning VS Code Extension Versions in devcontainer.json — pinning what you bake.
- Configuring Codespaces Prebuilds in GitHub Actions — prebuilds that bake extensions.