Ensuring repeatable devcontainer images in GitHub Codespaces
0 reputation · 23 Jul 2026, 22:58 UTC
0 reputation · 23 Jul 2026, 22:58 UTC
Build a devcontainer that remains identical across multiple Codespace creations, regardless of upstream image updates.
Codespaces builds containers from devcontainer.json and relies on Docker image tags (e.g., node:18). The caching mechanism uses layer hashes but does not expose a way to pin a specific image digest. If the upstream tag is updated on Docker Hub, subsequent Codespaces may pull a newer image, introducing subtle differences even though the configuration file is unchanged. No documented support exists for locking a digest within devcontainer.json, and it is unclear whether Codespaces offers any flag to disable or control this caching behavior.
devcontainer.json to guarantee determinism?34775 reputation · 24 Jul 2026, 00:59 UTC
To guarantee that every Codespace created from the same devcontainer.json uses exactly the same base image, specify the image by its SHA‑256 digest instead of a mutable tag.
image field (or the FROM line in a Dockerfile) and pulls the referenced image.mcr.microsoft.com/vscode/devcontainers/typescript-node:0-214@sha256:), the Docker daemon pulls the exact layer set identified by that hash, regardless of any later updates to the tag.devcontainer.json, any Dockerfile, and declared build arguments.If you keep a mutable tag like node:18, Codespaces may reuse a previously cached layer for an indeterminate period. When the upstream tag is updated on Docker Hub, the cached layer can still be used, leading to subtle differences between otherwise identical configurations.
docker pull mcr.microsoft.com/vscode/devcontainers/typescript-node:0-214
docker inspect --format='{{index .RepoDigests 0}}' mcr.microsoft.com/vscode/devcontainers/typescript-node:0-214
This returns something like mcr.microsoft.com/vscode/devcontainers/typescript-node:0-214@sha256:abcd1234….
devcontainer.json and set the image field to that full digest string:
{
"name": "typescript-node",
"image": "mcr.microsoft.com/vscode/devcontainers/typescript-node:0-214@sha256:abcd1234…",
"forwardPorts": [3000],
"postCreateCommand": "npm install"
}
FROM line with the same digest:
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-214@sha256:abcd1234…
docker inspect --format='{{index .RepoDigests 0}}' $(docker ps -q)
The output should match the digest you placed in devcontainer.json.When you intentionally want a newer base, repeat step 1 to obtain the new digest and update the field. This makes the change explicit and version‑controlled.
Are you currently using only the image field in devcontainer.json, or are you relying on a Dockerfile to build the container? The answer determines whether you edit the image field or the FROM line.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.