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.

Prebuild prerequisitesYou need the pinned list, a prebuild install step, a published image, and a fast attach.Extension listpinned IDsPrebuild stepinstall into serverPublish imagewith extensionsAttachinstant

Step-by-Step Implementation

  1. Declare pinned extensions.
{ "customizations": { "vscode": { "extensions": ["dbaeumer.vscode-eslint@3.0.10"] } }, "remoteUser": "vscode" }
  1. 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
  1. Publish the prebuilt image and reference it.

  2. Attach and confirm extensions are already present.

ls ~/.vscode-server/extensions | grep eslint

Attach time by strategyBaking extensions into a prebuilt image gives the fastest attach.Cold download62sCache volume8sPrebuilt image2sillustrative attach time

Common Pitfalls

Prebuild issues are unpinned extensions or a prebuild that doesn't cover the config.

Prebuild triageA triage path from slow attach to a prebuilt image with baked extensions.Are extensions in the prebuilt image?NOInstall them in the prebuildAre versions pinned?YESPrebuild rebuilds on config changeInstant, reproducible attach

SymptomRoot CauseRemediation
First attach still downloads extensionsNot baked into the imagePreinstall in the prebuild
Prebuilt extensions driftUnpinned versionsPin exact extension versions
Prebuild stale after adding an extensionNot rebuilt on config changeTrigger prebuild on config change
Image bloatedToo many extensions bakedBake 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.

Prebuild fitBaking extensions suits Codespaces prebuilds and large teams needing fast first attach.Prebuilt imageBaked extensionsBaked serverPinned versionsBest forCodespaces prebuildsLarge teamsFirst-attach speed

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.