Migrating from Docker to Podman in DevContainers

You're moving off Docker Desktop to rootless Podman and want your devcontainers to come along. This page migrates in place: point the tooling at Podman, add the keep-id mapping, and handle the two rootless differences — low ports and the Compose provider — so the same .devcontainer/ runs on Podman.

Prerequisites

You need rootless Podman installed and your existing devcontainer config.

  • Rootless Podman working (podman info).
  • Your existing .devcontainer/ config.
  • podman-compose if you use multi-service stacks.

Migration prerequisitesPoint the tooling at Podman, fix ownership, adjust ports, and set the Compose provider.Point toolingdockerPath=podmankeep-idownershipPorts>1024Composepodman-compose

Step-by-Step Implementation

  1. Point the tooling at Podman.
"dev.containers.dockerPath": "podman"
"dev.containers.dockerComposePath": "podman-compose"
  1. Add the userns mapping so file ownership stays correct.
{ "runArgs": ["--userns=keep-id"], "remoteUser": "vscode" }
  1. Raise any low ports above 1024.
{ "forwardPorts": [8080] }
  1. Verify the same config builds and attaches on Podman.
devcontainer up --workspace-folder .

Migration layersPoint the tooling at Podman, fix ownership and ports; the config is otherwise unchanged.Point at podmandockerPath/composePathkeep-idcorrect ownershipHigh portsrootless-friendlySame configotherwise unchanged

Common Pitfalls

Migration snags are ownership, low ports, or the Compose provider.

Migration triageA triage path from a Docker-only config to one running on rootless Podman.Does the tooling use podman now?NOSet dockerPath/composePathOwnership + ports correct?YESCompose provider setRuns on Podman

SymptomRoot CauseRemediation
Tooling still calls dockerdockerPath not setSet dev.containers.dockerPath to podman
Files root/subuid-ownedNo keep-idAdd --userns=keep-id
Low port fails to bindRootless can't bind <1024Forward a port above 1024
Compose stack failsDocker compose assumedSet dockerComposePath to podman-compose

Conclusion

Migrating to Podman is mostly configuration: point the tooling at podman, add keep-id for ownership, raise low ports, and set the Compose provider. The .devcontainer/ itself barely changes, so the same environment runs rootless with a smaller attack surface.

Change vs keepPoint the tooling at Podman and fix rootless nuances; keep the rest of the config.ChangedockerPath -> podmanAdd keep-idRaise low portsKeepBase imageFeaturesLifecycle hooks

FAQ

Will my Dockerfile and Features work on Podman? Yes — Podman builds OCI images and consumes Features the same way. The base image, Features, and lifecycle hooks are unchanged; you only adjust the engine path, add keep-id, and handle rootless ports and the Compose provider.

What breaks most often in the switch? File ownership (fixed with --userns=keep-id) and low ports (rootless can't bind below 1024). Address those two and most migrations are seamless. Multi-service stacks additionally need the compose provider pointed at podman-compose.

Can Docker and Podman coexist during migration? Yes. You can point the tooling at either engine, so team members can migrate individually. Keep the config host-agnostic (no engine-specific paths baked in) and the same .devcontainer/ works on both while you transition.