devcontainers / devcontainers/cli

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

Open
#1,300 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
3k
Forks
457
Avg merge
13h 17m
Merged PRs (30d)
6

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`

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

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

```json
{ "name": "co", "dockerComposeFile": "docker-compose.yml", "service": "app",
"workspaceFolder": "/workspace", "remoteUser": "vscode" }
```

```yaml
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 --format '{{.HostConfig.UsernsMode}} {{.HostConfig.SecurityOpt}}'
private [label=disable]

podman inspect --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.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.