Reading a devcontainer.json
The file from the previous module, annotated
Let's revisit exactly the file created in module 3:
{
"name": "My First Dev Container",
"image": "mcr.microsoft.com/devcontainers/javascript-node:20",
"forwardPorts": [3000]
}
name
A display name, purely descriptive. It shows up in VS Code's UI (bottom-left status bar, window picker) to identify the Dev Container without having to read the whole JSON. It has no functional effect on the container itself.
image
The most important field: the name of an image that's already built, published on a container registry. Here, mcr.microsoft.com/devcontainers/javascript-node:20 points to an official Microsoft image containing Node.js 20 on a Debian base. This is what Docker downloads and instantiates.
Alternative to image: the build field (not used in our example), which builds the image locally from a project Dockerfile rather than pulling it as-is from a registry — useful when you need a more specific environment than what a public image offers. A devcontainer.json uses one or the other, never both at once.
forwardPorts
An array of ports to make reachable from the host machine. Here, [3000] means: if a server is listening on port 3000 inside the container, it will also be reachable at localhost:3000 from your browser, on the host. Without this, a service running inside the container would stay invisible from the outside.
postCreateCommand (absent from our example, but common)
A command — or an array of commands — run automatically exactly once, right after the container has been created. Typically used to install the project's dependencies, for example "postCreateCommand": "npm install". Our module 3 example deliberately doesn't use it, to stay minimal, but it's a field you'll run into in almost every real-world devcontainer.json.
customizations.vscode.extensions (absent from our example, but common)
A nested object listing the VS Code extensions to install automatically in the instance connected to the container — for example a linter or language support specific to the project, so that everyone who opens the Dev Container has the same editor tooling, not just the same runtime.
Self-check exercise
Before continuing, look at this second devcontainer.json file and answer two questions, without scrolling down right away:
{
"name": "Python API",
"image": "mcr.microsoft.com/devcontainers/python:3.12",
"forwardPorts": [8000],
"postCreateCommand": "pip install -r requirements.txt",
"customizations": {
"vscode": {
"extensions": ["ms-python.python"]
}
}
}
- Which base image does this container use?
- Which port is made reachable from the host?
Answers
mcr.microsoft.com/devcontainers/python:3.12— an official image with Python 3.12 preinstalled.- Port
8000— typically the default port for a Django or FastAPI-style development server.
Bonus, if you also spotted the other two fields: postCreateCommand automatically installs the dependencies listed in requirements.txt as soon as the container is created, and customizations.vscode.extensions installs Microsoft's official Python extension so autocomplete and the Python debugger are ready immediately.
If you found both answers without rereading the annotation section, you know how to read a devcontainer.json. In the next module, we switch topics entirely: on to pre-commit.
Check your understanding
In the self-check exercise file (Python image, port 8000), which field indicates the command to run right after the container is created?
What happens if you use build.dockerfile instead of image in devcontainer.json?
What does customizations.vscode.extensions do in devcontainer.json?
Want to hear about the next modules?
The Academy stays free and open-access, no sign-up required. If you'd just like to be notified by email when a new module ships, here you go — no obligation, unsubscribe anytime with one click.