Skip to content

add PRE_COMMIT_CONTAINER_RUNTIME to select docker or podman - #3780

Closed
robjackstewart wants to merge 1 commit into
pre-commit:mainfrom
robjackstewart:container-runtime-env-var
Closed

robjackstewart wants to merge 1 commit into
pre-commit:mainfrom
robjackstewart:container-runtime-env-var

Conversation

@robjackstewart

Copy link
Copy Markdown

Add PRE_COMMIT_CONTAINER_RUNTIME to choose docker or podman

First of all, thank you for pre-commit. It's one of the few tools every team in our organisation has adopted without being told to: one config file, the same behaviour in every repo and on every OS, and it catches real problems (secrets, in our case, with a TruffleHog docker_image hook) before they leave a laptop.

What this does

It adds an opt-in environment variable, PRE_COMMIT_CONTAINER_RUNTIME, that selects the executable used by the docker and docker_image languages.

  • Unset, empty or whitespace-only: docker, exactly as today. Nothing changes unless you ask for it.
  • docker or podman: that executable is used. The value is trimmed and lowercased first, so " Podman " works.
  • Anything else (nerdctl, a path, podman --remote, ...) raises a FatalError naming the variable and the supported values. A typo is never silently ignored, and this can't be used to run an arbitrary executable.

_docker_exe() replaces the hard-coded 'docker' in the four places that call the runtime: build, run, system info (rootless detection) and inspect. docker_image picks it up through docker_cmd(), so there's no change in that file.

It follows the pattern languages/conda.py already uses (PRE_COMMIT_USE_MAMBA / PRE_COMMIT_USE_MICROMAMBA), and the name and the docker / podman values follow .NET Aspire's ASPIRE_CONTAINER_RUNTIME, which solves the same problem the same way.

Why

I know this has come up before, and that the usual answer is to symlink podman to docker. I read the earlier threads and tried to keep this within what you said in them:

Thread What was said How this PR respects it
#1243 "ideally just detect and adjust ... there is currently no configuration and I'd like to keep it that way" No new key in .pre-commit-config.yaml and no CLI flag. It's an environment variable, like PRE_COMMIT_HOME and PRE_COMMIT_USE_MAMBA.
#1243, #3676 Detection is preferred, and an automatic fallback to podman was declined No detection or fallback. On our machines both runtimes are installed and in use, so there's nothing to detect.
#2779 "can't take on that dependency" No new dependency.
#2173, #2920, #3676 Symlink an alternative runtime to docker That works on a machine with one runtime. See below for why it doesn't on ours.
#1484, #3446 Rootless detection Unchanged. It already reads Podman's system info output.
#2509, #2560 :Z on some mounts is an upstream Podman problem Out of scope. No change to mount flags.

Why a symlink doesn't work for us. Some of our teams use Docker Swarm and docker stack (docker swarm init/join, docker stack deploy, docker service, docker secret, docker config). Podman doesn't implement Swarm or stacks, so on those machines docker has to be real Docker. Other teams don't need Docker Desktop and are standardising on Podman, and plenty of developers do both. A symlink is one machine-wide choice of what docker means, so on a machine with both we'd have to pick between docker stack deploy and pre-commit.

Why an environment variable is better than a symlink or PATH shim:

  • It can be managed by policy. Organisations already distribute environment variables centrally (Intune / Group Policy, CI variables, direnv or devcontainer files). It's one declarative setting that can be audited and rolled back. A symlink is a hand-made change per machine that drifts.
  • It's less error-prone. A symlink depends on PATH order, which installers rewrite (Docker Desktop updates put its own bin back at the front and quietly undo the shim). A bad value for the variable fails loudly with a clear message. A bad symlink quietly runs the wrong runtime.
  • It behaves the same on every OS. The variable means the same thing on Linux, macOS and Windows. A symlink is ln -s on Unix but needs admin rights or Developer Mode on Windows, and a docker.cmd shim isn't a safe substitute because of how cmd.exe re-parses arguments.

I appreciate that the use case is narrow. I still think the tool is easier to use for everyone with an explicit, validated variable than with symlinks.

Testing

I added 15 tests to tests/languages/docker_test.py, written in the same style as the conda ones (envcontext, mock.patch.object):

  • the resolved executable for unset, empty, whitespace-only, docker, podman, PODMAN and " Podman "
  • FatalError for nerdctl, /usr/bin/podman, podman --remote and docker;podman, including that the message names the variable and the supported values
  • docker_cmd() and the rootless check use the selected runtime

All 15 pass on Windows 11. On the same machine, 5 existing test_docker_user_non_rootless tests fail with and without this change, because os.getuid doesn't exist on Windows. The repo's pre-commit hooks pass on the changed files, apart from mypy, which only reports Windows-only errors on lines I didn't touch (getuid, getgid, sched_getaffinity).

What I haven't done: I haven't yet run this against a live Podman engine, and I haven't run the suite on Linux or macOS, so I'm relying on CI for those.

Docs

The variables are documented in the separate pre-commit.com repo. If you're happy with the approach I'll send a PR there to add this one next to PRE_COMMIT_USE_MAMBA.

If this isn't something you want in pre-commit, I understand, and thank you for taking the time to look at it anyway.

An opt-in, validated environment variable that selects the executable
used by the docker and docker_image languages. Unset or empty keeps the
current behaviour (docker). Values are trimmed and lowercased and must be
docker or podman, anything else is a FatalError.
@asottile asottile closed this Oct 16, 2026
@pre-commit pre-commit locked as spam and limited conversation to collaborators Oct 16, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants