
Rebuilding a container from `podman inspect`: three fields that will break you (StopSignal, Runtime, and pod members)
I maintain a container update tool that speaks both Podman and Docker, and spent this week finding out that it has never once successfully updated a container on Podman. Not "worked badly" — never worked. Three differences between Podman's inspect output and Docker's, each fatal on its own, stacked so that fixing one only revealed the next. Writing them down because anyone reconstructing a podman run command from inspect output will hit all three, in this order.
Measured against podman 4.9.3.
1. Config.StopSignal is a number.
Podman reports 15. (Docker reports the string "SIGTERM", which is why my code assumed a string — my bug, not Podman's.) If you build your argument list from inspect output and hand it to subprocess, that integer goes straight in and Python refuses before the CLI is ever executed:
TypeError: expected str, bytes or os.PathLike object, not int
The traceback points inside subprocess, names no field, and tells you nothing about which key was wrong. Both CLIs accept the numeric form on the command line — it only ever needed to be a string.
2. HostConfig.Runtime is oci**.**
That is not the name of a runtime — it's the generic label for "whatever runtime is configured". Feed it back to podman run and:
Error: default OCI runtime "oci" not found: invalid argument
So: treat oci as "nothing to pass", and only forward a runtime somebody actually chose (crun, kata). Same as Docker's runc, which I was already skipping.
3. A container in a pod looks exactly like a network-namespace sidecar.
This is the interesting one. A pod member reports:
"NetworkMode": "container:<infra-container-id>"
which is indistinguishable in shape from the Gluetun pattern — a container joined to another container's network namespace. So the obvious reconstruction is --network container:<id>, and Podman refuses:
Error: container dependency <id> is part of a pod, but container is not: invalid argument
The answer is the top-level Pod field, which carries the pod id. --pod <id> works and the container rejoins the pod properly. Nice property compared to the sidecar case: a pod can't be recreated out from under its own member, so there's no stale-id problem — which is a real headache with container:<id> when the netns owner gets replaced.
The first two hit every container on Podman, not just pod members. Which means anyone who installed my tool on Podman got a rollback every time and no successful update, ever.
The part I'd rather admit than hide: I had a test file driving a real Podman for several releases. It checked that ps worked and that the remote-connection flag was right. It never once built a run command. What was tested was the part I'd already thought about.
Fixed in Docksentry 2.6.0 if you happen to use it. But the three inspect differences are the useful part here and they're not specific to my code — if you're doing anything similar, they'll bite you in that order.
Edit: point 1 only holds on Podman 4.x — StopSignal became the signal name in 5.0.0, listed as a breaking change in the release notes. It survives in a narrower form: the Docker-compat endpoint still returns a numeric string as of v6.0.2, and an older API version still gets an int, so the field has three shapes depending on how you ask. Points 2 and 3 check out against v6.0.2 source unchanged. Also, the fix shipped in 2.4.0, not 2.6.0 as written below. Thanks to u/Great-Cow7256 for the correction.