Skip to content

Podman: --userns=keep-id and --security-opt label=disable are never applied on the Docker Compose path #1300

Description

The problem

getPodmanArgs() — which adds --security-opt label=disable and, for a non-root remoteUser, --userns=keep-id — lives in src/spec-node/singleContainer.ts and is typed to DevContainerFromDockerfileConfig | DevContainerFromImageConfig. src/spec-node/dockerCompose.ts contains no podman handling at all, so a compose-based dev container on rootless podman gets neither flag.

Result: with rootless podman, the host user maps to container root, so a workspace bind mount appears as root:0 inside and the non-root remoteUser cannot write to it.

Reproduction

devcontainer CLI 0.87.0, podman 5.8.2 rootless, Linux. Two configs differing only in single-container vs compose, both "remoteUser": "vscode", same base image.

repro-sc/.devcontainer/devcontainer.json

{ "name": "sc", "image": "mcr.microsoft.com/devcontainers/base:ubuntu", "remoteUser": "vscode" }

repro-co/.devcontainer/devcontainer.json + docker-compose.yml

{ "name": "co", "dockerComposeFile": "docker-compose.yml", "service": "app",
  "workspaceFolder": "/workspace", "remoteUser": "vscode" }
services:
  app:
    image: mcr.microsoft.com/devcontainers/base:ubuntu
    command: sleep infinity
    volumes: [ "..:/workspace:cached" ]
devcontainer up --workspace-folder repro-sc --docker-path $(which podman) --docker-compose-path $(which docker-compose)
devcontainer up --workspace-folder repro-co --docker-path $(which podman) --docker-compose-path $(which docker-compose)

--docker-path/--docker-compose-path are explicit only to make podman detection unambiguous; lookupCLIVariant correctly reports Podman in both runs.

Result

podman inspect <sc> --format '{{.HostConfig.UsernsMode}} {{.HostConfig.SecurityOpt}}'
  private  [label=disable]

podman inspect <co> --format '{{.HostConfig.UsernsMode}} {{.HostConfig.SecurityOpt}}'
  (empty)  []

Both workspaces are dev:1000 on the host:

workspace owner inside write as remoteUser
single container vscode:1000 OK
compose root:0 Permission denied

Expected

The compose path should apply the same podman handling as the single-container path — emitting the flags into the generated docker-compose.devcontainer.*.yml override (userns_mode, security_opt) for the primary service.

Related but different

#1004 / #1018 (omit keep-id for root) and #1284 / #1285 (derive the mapping from the remote user's real UID/GID) all concern how getPodmanArgs should behave. This is that the compose path never calls it. Whatever #1285 settles for the mapping should presumably apply to both paths.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions