Skip to main content

literegistry-podman-client

literegistry-podman-client is a small, standalone async Python client for running commands in rootless Podman containers through a LiteRegistry gateway. The person using it needs only a gateway URL; they do not need Redis, Podman, Docker, or the full literegistry package.

The same gateway may also expose a Docker Hub pull-through mirror. Mirror use is configured on the Podman servers by the operator, so client code still only passes a normal image such as docker.io/library/ubuntu:24.04.

Install

From PyPI after publication:

pip install literegistry-podman-client

From this repository:

pip install ./literegistry_podman_client

The distribution name uses hyphens. Python imports use underscores:

from literegistry_podman_client import PodmanGatewayClient

Its only runtime dependency is aiohttp.

Give a deployment to someone

The operator gives the user one value:

export PODMAN_GATEWAY_URL=http://gateway.example:8080

The user can verify both gateway features:

curl -fsS "$PODMAN_GATEWAY_URL/health"
curl -fsS "$PODMAN_GATEWAY_URL/v2/"

/health checks the LiteRegistry gateway. /v2/ checks its Docker Registry V2 mirror route. No Redis URL or Podman replica address is exposed to users.

Small async example

This creates one container, writes a file, reads it in a separate command, and always deletes the container at the end:

import asyncio

from literegistry_podman_client import PodmanGatewayClient


async def main() -> None:
    gateway_url = "http://gateway.example:8080"

    async with PodmanGatewayClient(gateway_url, workdir="/tmp") as client:
        async with client.session(
            image="docker.io/library/ubuntu:24.04",
            client_id="rollout-17",
        ) as podman:
            print(podman.container_id)

            await podman.execute(
                "printf 'ai2 hello\\n' > hello.txt",
                check=True,
            )
            result = await podman.execute("cat hello.txt", check=True)
            print(result.stdout, end="")


asyncio.run(main())

The image pull happens on the selected Podman replica. If the operator wired those replicas to the gateway's mirror, the pull is transparently cached; the user does not change the image reference or client configuration.

The runnable version is examples/ai2_hello.py:

python literegistry_podman_client/examples/ai2_hello.py \
  --gateway "$PODMAN_GATEWAY_URL"

Explicit lifecycle

Handshake, execute, and close are all async. The affinity ID returned by the handshake keeps every command on the replica that owns its container.

client = PodmanGatewayClient(gateway_url, workdir="/home/user")
await client.open()
session = None
try:
    session = await client.handshake(image=container_image)
    first = await client.execute(
        session.affinity_id,
        "python -c 'print(6 * 7)'",
        timeout=60,
    )
    first.check_returncode()
finally:
    try:
        if session is not None:
            await session.close()
    finally:
        await client.aclose()
  • client.close(affinity_id) or session.close() deletes the container and its gateway affinity binding.
  • client.aclose() only closes the local HTTP connection pool. It cannot guess which concurrent sessions should be deleted.
  • check=True or result.check_returncode() raises PodmanCommandError for a non-zero command exit. Without it, stdout, stderr, and the exit code remain available on CommandResult.

Concurrent trajectories

One PodmanGatewayClient is intentionally shareable. It does not store a private "current container". Each handshake returns a separate session:

async def rollout(client: PodmanGatewayClient, number: int) -> str:
    async with client.session(client_id=f"rollout-{number}") as podman:
        result = await podman.execute("echo $((20 + 22))", check=True)
        return result.stdout.strip()


async with PodmanGatewayClient(gateway_url) as client:
    outputs = await asyncio.gather(
        *(rollout(client, i) for i in range(128))
    )

The HTTP pool is shared, while every request carries its explicit affinity ID. As soon as one trajectory completes, application code may start another.

Mirror behavior

There are two distinct flows behind the gateway URL:

Python client -> /affinity/* -> Podman replica -> rootless container
Podman pull   -> /v2/*       -> Docker mirror -> Docker Hub

The client exposes await client.mirror_health() as a convenience probe, but it does not configure the mirror. The deployment operator configures each Podman replica's containers-registries.conf to use the gateway URL. This is what ensures all users of the gateway benefit from the cache.

Build and publish

cd literegistry_podman_client
python -m build
python -m twine check dist/*
python -m twine upload dist/*

Publishing requires a PyPI account and token. Verify that the distribution name literegistry-podman-client is available before the first upload.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

literegistry_podman_client-0.1.0.tar.gz (11.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

literegistry_podman_client-0.1.0-py3-none-any.whl (8.6 kB view details)

Uploaded Python 3

File details

Details for the file literegistry_podman_client-0.1.0.tar.gz.

File metadata

File hashes

Hashes for literegistry_podman_client-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6ed5ddab4a7669be8dcd5187b577b9837acfd761dc637aa739c93ea123aa2336
MD5 d8e48a9c97b7b23cbd88290f6c8e64bb
BLAKE2b-256 7b88727cb89995a57e4bd61ebbbaf276f95a877a6753959a886fb475ef9ec86b

See more details on using hashes here.

File details

Details for the file literegistry_podman_client-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for literegistry_podman_client-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1fff4611ab55c455fc6cd79f48d88dae23b97d03ba5f5a80cdcd2f42d7e06ea1
MD5 870757d9407edf9384e6fb5f618131d6
BLAKE2b-256 5c2177d4f00ab36e6a6df8f1d89a29a0c8e411603dacf7272fd3edbd786b25f2

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

This release

0.1.0 This release

2 files

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