Choosing between Dev Containers vs Codespaces is really a choice between two execution models for the same core idea: a reproducible development environment defined as code. Local Dev Containers run in Docker on your machine, while GitHub Codespaces runs a dev container on a GitHub-hosted virtual machine and lets you connect from VS Code or the browser.
Both approaches can reduce “works on my machine” problems, speed up onboarding, and make project tooling more consistent. The right setup depends on your team’s hardware, collaboration style, security model, latency tolerance, and budget.
What Dev Containers and Codespaces Solve
Modern software projects often depend on a specific mix of language runtimes, package managers, databases, linters, extensions, ports, command-line tools, and environment variables. Without a standardized setup, every developer has to recreate that environment locally.
That creates familiar problems:
- Configuration drift: One developer has a different runtime, dependency version, or system package than another.
- Slow onboarding: New contributors spend hours installing tools before they can run the project.
- Cross-platform friction: Teams working across macOS, Windows, and Linux hit different setup issues.
- Project switching pain: Moving between repositories means switching toolchains, runtimes, and dependencies.
- Disposable environment gaps: Local machines accumulate state, which can hide bugs or make setup hard to reproduce.
Dev Containers and GitHub Codespaces address these problems by defining the development environment in repository configuration, usually under a .devcontainer directory.
GitHub Docs describes dev containers as Docker containers configured to provide a “fully featured development environment.” In Codespaces, every codespace uses a dev container hosted on a virtual machine.
A useful mental model: a Codespace is a dev container running in the cloud. A local Dev Container is the same pattern running on your machine through Docker.
The shared foundation is typically a devcontainer.json file. That file can define:
- Base image: The Linux image or container image used for development.
- Tools and runtimes: Languages, frameworks, and command-line utilities.
- VS Code extensions: Extensions installed automatically when the environment starts.
- Port forwarding: Ports exposed from the container to the host or browser.
- Post-create commands: Commands that install dependencies or run setup scripts.
- Dockerfile or image reference: A custom build or existing container image.
For example, GitHub’s documentation shows that a dev container can reference a Dockerfile:
{
"build": {
"dockerfile": "Dockerfile"
}
}
If no custom configuration is present, GitHub Codespaces can use a default Linux image. According to GitHub Docs, that default image includes runtime versions for popular languages including Python, Node, PHP, Java, Go, C++, Ruby, and .NET Core/C#, plus tools such as Git, GitHub CLI, yarn, openssh, and vim. It also includes tools for data science and machine learning, including JupyterLab and Conda.
Key Differences Between Local and Cloud Development
The main difference in Dev Containers vs Codespaces is where the environment runs.
A local Dev Container runs in Docker on your own machine. GitHub Codespaces runs the container on GitHub-hosted cloud infrastructure, inside a virtual machine, and you connect to it remotely.
| Area | Local Dev Containers | GitHub Codespaces |
|---|---|---|
| Execution location | Runs locally in Docker | Runs in the cloud on a GitHub-hosted virtual machine |
| Configuration model | Uses .devcontainer/devcontainer.json, often with Dockerfile or Docker Compose |
Uses the same dev container configuration model |
| Editor experience | Commonly opened through VS Code Dev Containers; other IDEs have added support according to source data | Can be accessed through VS Code or browser-based VS Code |
| Hardware dependency | Limited by local CPU, memory, storage, and Docker setup | Uses cloud VM resources; source data cites VM options from 2 cores / 8 GB RAM up to 32 cores / 128 GB RAM |
| Offline use | Possible once dependencies/images are available locally | Requires internet access |
| Setup requirement | Requires local Docker and editor integration | Reduces local machine setup; provisioning happens remotely |
| Portability | Portable across machines that can run the dev container | Accessible from almost anywhere with internet access |
| Cost model | Uses your local hardware; no cloud compute billing described in source data | Source data identifies Codespaces as a billed cloud service, though exact rates are not provided |
Local Dev Containers are often attractive when developers already have capable machines and Docker installed. They provide many of the same consistency benefits without moving compute to the cloud.
Codespaces becomes more compelling when local setup is difficult, hardware is inconsistent, contributors use many devices, or a team wants browser-based access to fully configured environments.
The Shared Configuration Advantage
A major point from the source data is that Codespaces and local Dev Containers can use the same devcontainer.json file. That means teams do not necessarily have to choose one forever.
You can define the environment once and support both workflows:
- Local developers open the repository in a Dev Container.
- Remote developers or contributors create a Codespace from the same repository.
- Teams with mixed needs use the same configuration as the foundation for both.
This is why a hybrid setup is often practical: the repository owns the environment definition, while each developer chooses where to run it.
Setup Complexity and Repository Configuration
Setting up either option starts with repository configuration. The standard convention is a .devcontainer directory containing a devcontainer.json file and, optionally, a Dockerfile or docker-compose.yml.
GitHub Docs says the devcontainer.json file is the primary file in a dev container configuration. It can define frameworks, tools, extensions, and port forwarding.
Common Dev Container File Layouts
| Setup Type | Files Used | Best Fit |
|---|---|---|
| Default configuration | No custom devcontainer.json |
Small projects that can use GitHub Codespaces’ default Linux image |
| Simple image-based setup | .devcontainer/devcontainer.json |
Projects that can use an existing image directly |
| Custom Dockerfile setup | .devcontainer/devcontainer.json + .devcontainer/Dockerfile |
Projects needing custom packages or system dependencies |
| Multi-service setup | .devcontainer/devcontainer.json + Dockerfile + docker-compose.yml |
Apps requiring services such as databases |
VS Code can generate dev container configuration files through the command palette using Remote-Containers: Add Development Container Configuration Files. The source data notes that predefined configurations can be easier for a first-time setup because they often include useful defaults such as a non-root user, a polished Bash prompt, and common tools.
For example, a Python and PostgreSQL project may generate:
.devcontainer/devcontainer.json.devcontainer/Dockerfile.devcontainer/docker-compose.yml
A source example for a Django-style setup included a devcontainer.json with Python-specific VS Code settings, Python extensions, forwarded ports, and a non-root user:
{
"name": "Python 3 & PostgreSQL",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"customizations": {
"vscode": {
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python"
},
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance"
]
}
},
"forwardPorts": [8000],
"remoteUser": "vscode"
}
The same source explains that forwarding port 8000 lets a Django development server running inside the container become available from the developer’s browser.
Dockerfile-Based Setup
A Dockerfile lets teams install operating system packages and dependencies into the development image.
One source example uses a Microsoft-managed Python dev container image and installs dependencies from requirements.txt:
ARG VARIANT=3-bullseye
FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}
ENV PYTHONUNBUFFERED 1
COPY requirements.txt /tmp/pip-tmp/
RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \
&& rm -rf /tmp/pip-tmp
Another source example for a Python environment uses:
FROM mcr.microsoft.com/devcontainers/python:0-3.11-bullseye
RUN apt-get update && apt-get install -y python3-pip
That example also includes a verification command:
docker run --rm mcr.microsoft.com/devcontainers/python:0-3.11-bullseye python3 --version
The expected output is Python 3.11.x, according to the source data.
Docker Compose for Multi-Service Development
For projects that need a database or other supporting service, Docker Compose can be part of the dev container setup.
The source data includes a PostgreSQL example:
version: '3.8'
services:
app:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
volumes:
- ..:/workspace:cached
command: sleep infinity
network_mode: service:db
db:
image: postgres:latest
restart: unless-stopped
volumes:
- postgres-data:/var/lib/postgresql/data
hostname: postgres
environment:
POSTGRES_DB: my_media
POSTGRES_USER: example
POSTGRES_PASSWORD: pass
POSTGRES_HOST_AUTH_METHOD: trust
ports:
- 5432:5432
volumes:
postgres-data:
This pattern is useful when development requires more than one process or service. The source example used PostgreSQL for a Python/Django project.
Multiple Dev Container Configurations
GitHub Docs also supports multiple dev container configurations in a repository. This is useful for large repositories with different projects, languages, or teams.
Example paths from GitHub Docs include:
.devcontainer/database-dev/devcontainer.json.devcontainer/gui-dev/devcontainer.json
Each codespace is created from only one configuration. GitHub Docs notes that settings cannot be imported or inherited between devcontainer.json files, so dependent files such as Dockerfiles or scripts should be co-located in the same subdirectory.
Performance, Latency, and Resource Limits
Performance is one of the most practical decision points in Dev Containers vs Codespaces.
Local Dev Containers use your machine’s CPU, memory, disk, network, and Docker runtime. Codespaces uses cloud-hosted virtual machines. The source data states that Codespaces VM configurations range from 2 cores and 8 GB RAM up to 32 cores and 128 GB RAM.
| Performance Factor | Local Dev Containers | GitHub Codespaces |
|---|---|---|
| Compute power | Depends on developer laptop or workstation | Can use cloud VM configurations cited from 2 cores / 8 GB RAM to 32 cores / 128 GB RAM |
| Startup time | First run can be slower while images pull and build; later starts can be faster if images are cached | Provisioning happens in the cloud; exact timing not specified in source data |
| Latency | Editor-to-container path is local | Remote connection depends on internet quality |
| Large builds | Limited by local resources | May benefit from larger cloud VM options |
| Offline work | More feasible once Docker images and dependencies are available | Not suitable without internet access |
| Browser development | Not the primary model in source data | Browser-based VS Code access is supported |
A practical intro source notes that the first local Dev Container run can be slow because Docker has to pull and build the image. Subsequent starts can be faster as long as the image does not need to be rebuilt. The same source mentions advanced options for improving startup time by pre-building containers, but does not provide benchmark data.
Codespaces can potentially provide better performance than a developer’s laptop because compute runs on cloud hardware. However, that benefit depends on the selected VM size and the project workload. The source data does not provide build benchmarks, cold-start timings, or latency measurements, so teams should evaluate performance using their own repositories.
Do not assume cloud is automatically faster. Codespaces can offer larger remote resources, but local Dev Containers avoid network dependency and may feel more responsive for some workflows.
Port Forwarding and Browser Preview
Both approaches support port forwarding. In local Dev Containers, forwarding makes container ports available to the host machine. In Codespaces, source data mentions improved browser preview and port forwarding capabilities in 2026, including the ability to preview changes and share ports with teammates for feedback.
Common examples from the source data include:
- Port 8000: Used for a Python/Django development server.
- Port 8080: Shown in a sample
devcontainer.json. - Port 5432: Used for PostgreSQL in a Docker Compose example.
A minimal port-forwarding example:
{
"forwardPorts": [8000]
}
Team Onboarding and Environment Consistency
The strongest case for both tools is onboarding and consistency.
Instead of asking a developer to install every runtime, database, extension, and tool manually, the repository can describe the environment. A developer opens the project, and the environment is built from the same configuration.
A practical source describes a small open-source project using 12+ scripting languages. Rather than installing every language on a laptop, the maintainer used Docker and then migrated to a true VS Code Dev Container. That example shows the value of a disposable workspace with all required tools installed.
Another source describes a team working on a Jekyll blog with plugins and dependencies. The original setup worked on an Intel Mac, but the team later included developers using M1 Macs, Linux, and Windows. Dev Containers with Codespaces made the environment more portable and reduced setup friction.
What to Standardize
GitHub Docs recommends thinking of devcontainer.json as customization, not personalization.
That distinction matters:
Include in devcontainer.json |
Keep Personal |
|---|---|
| Linters needed by the project | Themes |
| Language runtimes | UI decorators |
| Required VS Code extensions | Personal editor preferences |
| Port forwarding | Individual workflows not needed by the team |
| Post-create dependency install commands | Personal shell aliases unless handled through dotfiles |
| Shared tools and frameworks | Private preferences |
GitHub Docs specifically says linters are good to standardize because everyone working on the codebase should have them installed. Themes and UI decorations are personal choices and should not be placed in shared configuration.
For personalization, source data points to dotfiles and Settings Sync. A practical source also notes that VS Code Dev Containers can share Git credentials through a Git credentials helper or SSH agent forwarding.
Onboarding Workflow Example
A team onboarding workflow might look like this:
- Clone repository: Developer gets the project locally or opens it in GitHub.
- Open in container: Local users open the folder in a Dev Container; cloud users create a Codespace.
- Build environment: Dockerfile, image, or default image provides runtime dependencies.
- Run post-create command: Dependencies install automatically, such as
pip3 install --user -r requirements.txt. - Use forwarded ports: App server is available through forwarded ports.
- Start developing: Terminal, debugger, extensions, and tools are ready inside the environment.
Example postCreateCommand from source data:
{
"postCreateCommand": "pip3 install --user -r requirements.txt"
}
This is especially helpful for distributed teams because every developer starts from the same documented baseline.
Security, Secrets, and Access Control
Security considerations differ between local Dev Containers and Codespaces because one runs on developer hardware and the other runs in a cloud-hosted environment connected to GitHub.
GitHub Docs states that people with write permissions to a repository can create or edit the codespace configuration. That matters because devcontainer.json, Dockerfiles, and setup scripts can influence what runs when a development environment is created.
Security-Relevant Configuration Areas
| Area | Why It Matters | Source-Grounded Guidance |
|---|---|---|
| Repository permissions | Dev container configuration can affect environments | GitHub Docs says people with write permissions can create or edit codespace configuration |
| Base images | Images define the operating system and installed software | Use trusted sources; source best practices mention official images from Microsoft or Dev Container Spec Maintainers |
| Image policies | Organizations may restrict allowed images | GitHub Docs states a base image must match organization image policy if one is configured |
| Dependencies | Outdated dependencies can introduce risk | Source best practices recommend keeping dependencies updated |
| Dev Container Features | Features add tooling to the environment | Source data mentions Dependabot integration for keeping Dev Container Features up to date |
| Secrets and credentials | Containers may need Git, SSH, or app credentials | Source data mentions Git credential helper and SSH agent forwarding for Dev Containers |
| Port sharing | Exposed ports can reveal running services | Source data notes Codespaces supports port forwarding and sharing ports with teammates |
GitHub Docs explains that if a configured base image does not match an organization’s base image policy, codespaces for that repository will be created in recovery mode.
A source also recommends using official images from trusted sources, including Microsoft or the Dev Container Spec Maintainers, and keeping dependencies updated for security and compatibility.
Credential Handling
The source data specifically mentions mechanisms for sharing Git credentials with local Dev Containers:
- Git credentials helper
- SSH agent forwarding
It also mentions dotfiles for personalization. That can help developers keep personal shell and tool configuration separate from project-wide configuration.
For Codespaces, the provided source data emphasizes integration with GitHub security features such as:
- Automatic dependency updates
- Vulnerability scanning
- Dependabot integration for Dev Container Features
The research does not include a full secrets-management comparison or exact policy controls beyond the points above, so teams should validate the current GitHub Codespaces security settings against their organization’s requirements at the time of writing.
Treat
.devcontainerfiles like application infrastructure. Review Dockerfiles, post-create scripts, and Dev Container Features because they define executable setup behavior for the team.
Cost Considerations for Individuals and Teams
Cost is one of the clearest differences between local Dev Containers and Codespaces, but the provided source data does not include current per-hour prices or included usage quotas.
What the sources do support:
- Local Dev Containers run on your own machine using Docker.
- GitHub Codespaces is described as a billed cloud service.
- GitHub Docs states that GitHub does not charge for storage of containers built from the default dev container image.
- Exact compute pricing, free allowances, storage rates, and organization billing details are not included in the provided research.
| Cost Factor | Local Dev Containers | GitHub Codespaces |
|---|---|---|
| Compute cost | Uses local hardware; no cloud compute billing described in source data | Billed cloud service according to source data |
| Hardware investment | Requires developer machines capable of running Docker and the project workload | Can reduce dependence on powerful local machines |
| Storage | Uses local disk | GitHub Docs says there is no charge for storage of containers built from the default dev container image |
| Team budget control | Managed through device provisioning and local setup | Requires monitoring cloud development usage; exact rates not provided |
| Occasional contributors | May need local Docker setup | Can start from a browser or VS Code with less local setup |
For individuals, local Dev Containers are often appealing when Docker is already installed and the machine has sufficient resources. The main “cost” is local CPU, memory, storage, setup time, and troubleshooting.
For teams, Codespaces may shift some costs away from laptop provisioning and onboarding time toward cloud usage. But because the source data does not provide exact pricing, teams should check current GitHub billing details before standardizing on Codespaces for all development.
Hidden Cost: Setup and Support Time
Although not expressed as a dollar figure in the sources, multiple examples highlight setup friction:
- A project with 12+ languages is hard to support locally without containerization.
- A team split across M1 Macs, Linux, and Windows had trouble with a locally configured Jekyll blog.
- Developers switching between projects often have to reconfigure tools and dependencies.
Dev Containers and Codespaces reduce that operational burden by making the environment reproducible and repository-defined.
Best Scenarios for Dev Containers, Codespaces, or Both
The best answer to Dev Containers vs Codespaces is not always either/or. Because both can use the same dev container configuration, many teams should start by standardizing .devcontainer and then decide where it should run.
Choose Local Dev Containers When
Local Dev Containers are a strong fit when:
- Developer machines are capable: The team’s laptops or workstations can run Docker and project services comfortably.
- Offline work matters: Developers need to work without reliable internet access.
- Latency sensitivity is high: The team prefers local editor-to-runtime responsiveness.
- Cloud cost needs to be minimized: The source data identifies Codespaces as billed, while local containers use existing hardware.
- Docker is already familiar: The team can maintain Dockerfiles and Compose files.
- You want Codespaces-like consistency without cloud hosting: Local Dev Containers provide disposable, standardized environments.
A practical source describes local Dev Containers as “almost exactly like GitHub Codespaces,” except they run locally in Docker rather than in the cloud.
Choose GitHub Codespaces When
GitHub Codespaces is a strong fit when:
- Onboarding speed is critical: Developers can create a cloud environment from a repository without local environment setup.
- Hardware varies across the team: Codespaces can provide cloud VM resources, with source-cited configurations ranging from 2 cores / 8 GB RAM to 32 cores / 128 GB RAM.
- Browser-based development is useful: Codespaces supports development from the browser through VS Code.
- Remote collaboration matters: Source data mentions shared codespaces for simultaneous editing, debugging, and testing.
- Reviewing branches, commits, or pull requests needs isolation: Codespaces can be created from a template, branch, or commit according to the source data.
- Port sharing helps feedback loops: Source data mentions improved browser preview and port forwarding capabilities, including sharing ports with teammates.
Codespaces is especially useful for distributed teams and contributors who should not have to configure a full local stack before making a change.
Choose a Hybrid Setup When
A hybrid setup is often the most flexible path.
Use the same .devcontainer configuration for:
- Local development by full-time engineers with powerful machines.
- Cloud development for contractors, reviewers, support engineers, or contributors.
- Pair programming where a shared remote environment helps.
- Complex repositories where different teams need different configurations.
- Project switching where isolated environments prevent dependency conflicts.
A hybrid setup also lets teams adopt the pattern incrementally. Start with local Dev Containers to codify the environment, then enable Codespaces for workflows that benefit from cloud provisioning.
Decision Matrix
| Scenario | Best Fit | Why |
|---|---|---|
| Small project using common tools in GitHub’s default image | Codespaces or local Dev Container | GitHub Docs says the default image is good for small projects using included tools |
| Project with many language runtimes | Dev Container foundation, local or Codespaces | Source example with 12+ scripting languages shows value of bundled tooling |
| Team split across macOS, Windows, Linux, and M1 Macs | Hybrid or Codespaces | Source example shows portability benefits across varied machines |
| Database-backed app needing PostgreSQL | Local Dev Container or Codespaces with Docker Compose | Source example uses docker-compose.yml for PostgreSQL |
| Developers need offline access | Local Dev Containers | Codespaces requires cloud access |
| New contributors need fast setup from a browser | Codespaces | Cloud-hosted browser-accessible environment reduces local setup |
| Team wants one environment definition for all developers | Hybrid | Both approaches can share devcontainer.json |
| Strict cloud cost control | Local Dev Containers or selective Codespaces | Codespaces is billed; exact rates are not included in the research |
Bottom Line
Dev Containers vs Codespaces is best understood as local reproducible environments versus cloud-hosted reproducible environments. Both rely on dev container configuration, especially devcontainer.json, and both can standardize tools, runtimes, extensions, ports, and setup commands.
Use local Dev Containers when your team has capable machines, needs offline work, wants low-latency local execution, or prefers to avoid cloud development billing. Use GitHub Codespaces when onboarding speed, browser access, remote collaboration, consistent cloud resources, and GitHub-integrated workflows matter more.
For many teams, the strongest strategy is hybrid: put the environment definition in the repository once, then let developers run it locally or in Codespaces depending on the task.
FAQ
1. Are Dev Containers and GitHub Codespaces the same thing?
Not exactly. A Dev Container is a Docker-based development environment defined by configuration files such as devcontainer.json. GitHub Codespaces runs a dev container in the cloud on a GitHub-hosted virtual machine.
A practical way to say it: all Codespaces use dev containers, but not all Dev Containers run in Codespaces.
2. Do Codespaces and local Dev Containers use the same configuration?
Yes, they can. The source data states that GitHub Codespaces uses the same devcontainer.json file that a local Dev Container would use.
That makes hybrid workflows practical because one repository configuration can support both local Docker-based development and cloud-hosted Codespaces.
3. What files do I need to create a Dev Container?
The primary file is usually:
.devcontainer/devcontainer.json
Depending on the project, you may also use:
.devcontainer/Dockerfile.devcontainer/docker-compose.yml- Scripts referenced by setup commands
VS Code can generate starter configuration files through the command palette using Remote-Containers: Add Development Container Configuration Files.
4. Can I use a Dev Container without writing a Dockerfile?
Yes. GitHub Docs says you can use the image property in devcontainer.json to refer directly to an existing image. If neither a Dockerfile nor image is found in Codespaces, GitHub can use the default container image.
The default Codespaces image includes many popular runtimes and tools, including Python, Node, PHP, Java, Go, C++, Ruby, .NET Core/C#, Git, GitHub CLI, yarn, openssh, vim, JupyterLab, and Conda.
5. Is Codespaces faster than local Dev Containers?
Not always. Source data says Codespaces can provide better performance than a laptop in some cases, and cites VM configurations from 2 cores / 8 GB RAM up to 32 cores / 128 GB RAM.
However, local Dev Containers avoid network dependency and run directly on your machine. The provided research does not include benchmark data, so teams should test with their own repositories.
6. Should personal editor preferences go in devcontainer.json?
Usually no. GitHub Docs recommends treating devcontainer.json as environment customization for the whole project, not personalization.
Shared tools such as linters, runtimes, required extensions, and ports are good candidates. Personal themes, UI decorators, and individual preferences should be handled separately through dotfiles or settings synchronization.










