Skip to main content

compose2pod

PyPI version Supported Python versions Downloads Coverage CI License GitHub stars Context7 uv Ruff ty

Convert a Docker Compose file into a POSIX sh script that runs its services as a single Podman pod.

Built for CI and test environments where you can't use docker compose or podman kube play:

  • No bridge networking or netavark. Unprivileged CI containers often have a read-only /proc/sys, so netavark fails to create bridge networks. A single pod shares one network namespace with no bridge: services talk over 127.0.0.1, and names resolve via a generated /etc/hosts the script owns.
  • No systemd. Podman healthchecks are normally scheduled by systemd timers. compose2pod gates startup by polling podman healthcheck run directly, so depends_on: service_healthy works without systemd.
  • No heavy runtime. The core is stdlib-only, with no dependencies and no compiled wheels, so it installs and runs in minimal Python images.

Requirements

Podman 4.9 or newer. compose2pod accepts only forms that every Podman from 4.9 to 6.1 can run, so a script it generates runs on any of them (ADR-0006).

compose2pod's generated scripts own /etc/hosts: they write it to a temp file and bind-mount it read-only into every container under --no-hosts, so pod-internal name resolution works on any Podman version. host.containers.internal / host.docker.internal are not provided; add an explicit extra_hosts entry if you need them.

Install

pip install compose2pod            # core: reads compose as JSON
pip install 'compose2pod[yaml]'    # optional: read YAML directly (adds PyYAML)

Usage

# YAML directly (needs the 'compose2pod[yaml]' extra)
compose2pod docker-compose.yml --target app --image myimage:ci > run.sh

# Or stay dependency-free by piping JSON (e.g. via yq)
yq -o=json '.' docker-compose.yml | compose2pod --target app --image myimage:ci > run.sh

sh ./run.sh

Options:

  • --target: the service to run in the foreground (required).
  • --image: the CI image that replaces every service with a build section (required).
  • --command: a shell command overriding the target service's command.
  • --project-dir: the host path that relative volume and env_file sources resolve against (default .).
  • --pod-name: the name of the Podman pod, also used as the prefix of every container name (default test-pod).
  • --format: the input format, one of auto, json, yaml (default auto, which tries JSON, then YAML).
  • --artifact SRC:DST: a file to podman cp out of the target container after it exits (repeatable).
  • --allow-exit-code: a target exit code treated as success in addition to 0 (repeatable).

Supported compose subset

compose2pod refuses every document docker compose config refuses. A test harness runs docker compose config and compose2pod over the same files to check this. So a file that compiles is a file Docker would run; where compose2pod still refuses a form Docker accepts, it is because Podman cannot express it; each case is documented in docs/adr/.

Within that boundary it covers most of what real compose files use:

  • Services: image/build, command/entrypoint, environment and env_file (string and long-form {path, required, format}), volumes (short-form and long-form --mount, including the bind and tmpfs option maps), tmpfs, healthcheck, depends_on (all conditions), links (read as a dependency plus a hostname alias, as Docker reads it), network aliases, hostname/container_name.
  • Confinement and metadata: user, working_dir, read_only, init, privileged, cap_add/cap_drop, security_opt, devices, group_add, platform, labels, annotations, pull_policy (the quoted-boolean and YAML-1.1 spellings Docker accepts, too).
  • Resources: the legacy keys (mem_limit, cpus, pids_limit, ulimits, …) and the modern deploy.resources block.
  • Pod-wide: dns/dns_search/dns_opt, sysctls, extra_hosts.
  • Composition: same-file extends, secrets/configs.

Accepted and ignored with a warning, since they mean nothing inside one shared pod: ports, expose, restart, stdin_open, tty, stop_signal, stop_grace_period, and profiles (every service runs regardless of profile).

Compose extension fields (any x--prefixed key) and YAML anchors are accepted as-is, so a top-level x-* anchor block for shared config is accepted. ${VAR}-style variable interpolation is left live in the generated script, resolved by its shell against the environment present when the script runs (no .env file support). The boundary rulings, which forms are refused and why, are recorded in docs/adr/.

Status

Beta.

Part of modern-python

Browse the full list of templates and libraries in modern-python; see the org profile for the categorized index.

Metadata

Release files for compose2pod 0.7.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for compose2pod 0.7.2
File Size Uploaded Provenance
compose2pod-0.7.2.tar.gz 66.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for compose2pod 0.7.2
File Interpreter ABI Platform
compose2pod-0.7.2-py3-none-any.whl Python 3 none any Details

Total release size: 139.9 kB

Release files / compose2pod-0.7.2.tar.gz

Download URL compose2pod-0.7.2.tar.gz
Size 66.2 kB
Tags Source
SHA-256 checksum
How to use checksums
799f757188d20c0b52179f6223d8fa9647a4923d8672f8db9101b1a0d01e8972
BLAKE2b-256 checksum
How to use checksums
fec8ff28be80e93860a5cd34ab9a15e689f6669cbe9c0063c72317730bbab9a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / compose2pod-0.7.2-py3-none-any.whl

Download URL compose2pod-0.7.2-py3-none-any.whl
Size 73.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
132872777bacb5f41972c9dde870d340f2a1da928398913dc064d019926073a0
BLAKE2b-256 checksum
How to use checksums
cf2cc1e35c6ead91496ea883edaa11dc6e229719e6e90c292f88b77b0ac01b9f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for compose2pod 0.7.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page