Separate the two workspace decisions

Decide first which host files enter the container, then decide where connected tools begin. The Dev Container materials treat the mounted workspace location and the folder opened by tools as separate settings.

A bind mount maps a host file or directory into a container path. For a Git project, the specification describes the repository root, where .git is found, as the usual workspace source; it also allows the tool-facing folder to be a lower-level directory. That distinction is useful when developers work in one package but repository-wide files still matter.

This article proposes topology choices rather than a provider-prescribed implementation. Select paths and ownership to match the repository, service model, and host-access requirements.

Four-case boundary decision table

Use one owner for the primary source mapping. The entries below are bounded policies, not executable configuration or claims of a tested outcome.

Workspace-boundary choices
CaseConfiguration ownerMounted source rootWorking folderSource-control visibilityRejected boundaryBounded application-owned action
Single repository with image or DockerfileFor image and Dockerfile setups, devcontainer.json can define the workspace mapping.Repository root.Project root inside the container.The selected root keeps its .git directory within the proposed mount boundary.A narrower source path that omits required repository files.Set the mount boundary at the repository root and open the project root.
Monorepo with repository root mounted and a subproject workspaceFolderFor image and Dockerfile setups, devcontainer.json can also choose the folder tools open.Monorepo root.A selected package, such as packages/api.Repository metadata remains reachable beneath the mounted root.Mounting only the active package when repository-wide access is needed.Keep the root mapping, but direct tools to the selected package.
Docker Compose-managed source mountIn a Compose scenario, the service configuration supplies the workspace mount, while Dev Container tooling identifies the service to connect to.The repository root selected by that service.The container folder selected for connected tools.Available only when the service mapping includes the relevant repository path.Defining competing primary source boundaries without an ownership decision.Make the Compose service the source-mount authority and document the tool start folder separately.
Additional shared or persistent data mountAn extra local bind can be expressed through devcontainer.json for image or Dockerfile use, or on the relevant Compose service.A host directory for shared files, or a Docker-managed volume for application data.Not applicable unless tools must open that data path.Only files under a chosen bind source are exposed through that mapping.Using a Docker-managed volume when direct host-file access is required.Use a bind for host-visible sharing; consider a volume for container-generated persistent data.

Why source mounts and data mounts differ

Docker-managed volumes are persistent stores maintained by Docker, whereas bind mounts use a host filesystem location. Docker presents volumes as the preferred persistence mechanism for data created and consumed by containers, while bind mounts suit cases that need host-side file access.

Account for existing container content before choosing either mechanism. A bind mounted over a populated container directory masks what was already there. An empty volume can instead receive pre-existing target content by default; Docker documents volume-nocopy for suppressing that initialization behavior.

For local additional mounts, exclude GitHub Codespaces from this policy: the supplied VS Code guidance says local filesystem mounting is unsupported there. Remote-host and identity or permission rules require separate review.

Hypothetical monorepo failure walkthrough

Consider an explicitly hypothetical setup: only packages/api is mounted; an edited host file sits outside that source path; and there is neither another mount nor a synchronization process. Assume .git is at the monorepo root, so it is unavailable in this container layout.

That absence follows from the declared topology: a bind mapping exposes its selected host source at its container destination, not files outside the selected source. If the chosen source-control operation requires .git, it fails in this hypothetical. The in-flight host edit is likewise inaccessible through this mapping because its path lies outside the declared source.

The proposed correction is to mount the monorepo root while leaving packages/api as the folder where connected tools start. This retains a narrow daily working location without treating the package directory as the entire repository boundary.

Limits and review points

This guidance makes no performance, synchronization, compatibility, or execution claim. Before adoption, confirm the target Dev Container and Docker release behavior, decide which Compose file owns the primary mapping, and review permissions for the chosen host paths.

Revisit the decision when sources change, when a version is retired, or when an incompatible release is introduced.