From 2b79411b689f054296a950b0ef04cf2d55473b3b Mon Sep 17 00:00:00 2001 From: magges Date: Sun, 12 Jul 2026 18:35:38 +0000 Subject: [PATCH] Replace vendored docker-compose with podman-compose podman-compose and docker-compose aren't discovered the same way by `podman compose` - verified live (a fake-binary test reading podman's own provider-search error output) that docker-compose is searched for by exact path across a fixed list of CLI-plugin directories, while podman-compose is instead looked up as a plain command on $PATH. This package installs to /usr/local/bin/podman-compose accordingly, not under any cli-plugins/ directory. Unlike docker-compose (a single static Go binary), podman-compose is a Python script with two runtime dependencies neither of which ship with Unraid's own Python3 - PyYAML and python-dotenv, vendored here as plain pure-Python source (no C extension build; PyYAML's own fallback handles its optional C accelerator being absent). Verified end-to-end on a real host: with the previous docker-compose binary temporarily moved aside to confirm podman-compose was actually the one invoked, `podman compose up/ps/down` ran a real compose project correctly, including a live HTTP check against the started service. Co-Authored-By: Claude Sonnet 5 --- .github/workflows/build-packages.yml | 2 +- docs/ARCHITECTURE.md | 2 +- packages/docker-compose/README.md | 31 ------- .../docker-compose/docker-compose.SlackBuild | 60 -------------- packages/docker-compose/slack-desc | 19 ----- packages/podman-compose/README.md | 34 ++++++++ .../podman-compose/podman-compose.SlackBuild | 83 +++++++++++++++++++ packages/podman-compose/slack-desc | 19 +++++ plugin/podman.plg | 24 +++--- plugin/sbin/podman-update-packages.sh | 2 +- plugin/sbin/podman-verify-packages.sh | 2 +- scripts/build-packages.sh | 14 ++-- scripts/release.sh | 4 +- versions.env | 44 ++++++---- 14 files changed, 191 insertions(+), 149 deletions(-) delete mode 100644 packages/docker-compose/README.md delete mode 100755 packages/docker-compose/docker-compose.SlackBuild delete mode 100644 packages/docker-compose/slack-desc create mode 100644 packages/podman-compose/README.md create mode 100644 packages/podman-compose/podman-compose.SlackBuild create mode 100644 packages/podman-compose/slack-desc diff --git a/.github/workflows/build-packages.yml b/.github/workflows/build-packages.yml index aef9fac..797b18e 100644 --- a/.github/workflows/build-packages.yml +++ b/.github/workflows/build-packages.yml @@ -2,7 +2,7 @@ name: Build Packages # Builds the eleven Slackware .txz packages defined under packages/ # (podman, conmon, crun, netavark, aardvark-dns, passt, fuse-overlayfs, -# catatonit, nftables, docker-compose, unraid-podman) inside a Slackware +# catatonit, nftables, podman-compose, unraid-podman) inside a Slackware # container, verifies + consolidates their checksums, and uploads the # result as a workflow artifact. # diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 763e3b9..6357c76 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -233,7 +233,7 @@ wählen können — mit deutlicher GUI-Warnung bzgl. Performance und Spin-up-Ver | `passt`/`pasta` | Rootless-Networking | Nachfolger von slirp4netns, Phase 2, aber Paket schon mitbauen (geringe Kosten) | | `catatonit` oder `tini` | Init-Prozess in Containern (optional, falls von Templates genutzt) | | | `nftables` | Firewall-Backend für `netavark` | Pflicht seit netavark 2.0 (iptables-Treiber entfernt); Unraid liefert kein `nft` mit — als offizielles Slackware-Paket vendored, nicht selbst gebaut | -| `docker-compose` (CLI-Plugin) | External-Compose-Provider für `podman compose` | `podman compose` hat keine eigene Compose-Implementierung, sondern sucht ein `docker-compose`-Binary in festen CLI-Plugin-Pfaden; ohne dieses Paket schlägt jede Compose-Panel-Aktion auf einem frischen Unraid-Install fehl | +| `podman-compose` | External-Compose-Provider für `podman compose` | `podman compose` hat keine eigene Compose-Implementierung, sondern sucht ein Kommando namens `podman-compose` auf `$PATH` (live verifiziert — anders als das ältere, ebenfalls unterstützte `docker-compose`, das stattdessen in festen CLI-Plugin-Pfaden gesucht wird); ohne dieses Paket schlägt jede Compose-Panel-Aktion auf einem frischen Unraid-Install fehl. Python-Skript, vendored zusammen mit PyYAML/python-dotenv als reines Python-Source (kein C-Build) | ### 5.2 Build-Strategie diff --git a/packages/docker-compose/README.md b/packages/docker-compose/README.md deleted file mode 100644 index 99a7cc0..0000000 --- a/packages/docker-compose/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# packages/docker-compose/ - -Pinned version: see `DOCKER_COMPOSE_VERSION` in [versions.env](../../versions.env). - -Not built from source — `docker-compose.SlackBuild` fetches and repackages -upstream's own prebuilt static x86_64 release binary (`docker/compose`, -the Go-based Compose v2 CLI plugin — a different project from the older -Python `podman-compose`). It's a small, purely static ELF with zero -runtime library dependencies (verified: `ldd` reports "not a dynamic -executable"), so there's nothing meaningful to gain from a from-source -build. - -`podman compose` (backing the WebUI's Compose panel, see -`webui/plugins/podman/ajax/compose.php`) has no compose implementation of -its own — it shells out to an "external compose provider" it discovers by -searching a fixed list of CLI-plugin directories for a binary named -`docker-compose`. Without one present, every Compose panel action fails -outright. Installed to `/usr/local/lib/docker/cli-plugins/docker-compose` -— one of podman's own search paths (extracted from the pinned podman -binary: `strings /usr/bin/podman | grep cli-plugins`), chosen specifically -under `/usr/local/` rather than `/usr/lib/docker/...` so this package -never collides with (or gets silently shadowed by) a genuine Docker -installation's own compose plugin on hosts that also run Unraid's -built-in Docker support. - -Found by live-testing the Compose panel end-to-end against a real Unraid -install: it happened to work only because that particular host already -had Docker's own `docker-compose` plugin installed from an unrelated, -pre-existing Docker setup — a clean Unraid install has no compose -provider at all without this package. See -[docs/ARCHITECTURE.md, section 5.1](../../docs/ARCHITECTURE.md#51-zu-paketierende-komponenten). diff --git a/packages/docker-compose/docker-compose.SlackBuild b/packages/docker-compose/docker-compose.SlackBuild deleted file mode 100755 index a6a6eed..0000000 --- a/packages/docker-compose/docker-compose.SlackBuild +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash -# ============================================================================= -# packages/docker-compose/docker-compose.SlackBuild -# -# Packages the official prebuilt docker/compose v2 release binary — not -# built from source, see versions.env's DOCKER_COMPOSE_* block for why. -# `podman compose` (backing webui/plugins/podman/ajax/compose.php) has no -# compose implementation of its own; it shells out to an "external compose -# provider" it discovers by searching a fixed list of CLI-plugin -# directories for a binary literally named `docker-compose` (paths -# extracted from the pinned podman binary itself: -# `strings /usr/bin/podman | grep cli-plugins`). Without one present, -# every Compose panel action fails outright (found by live-testing against -# a real Unraid install — it only worked there because that host happened -# to already have Docker's own compose plugin from an unrelated setup). -# -# Installed to /usr/local/lib/docker/cli-plugins/docker-compose — one of -# podman's search paths, deliberately the /usr/local/ one rather than -# /usr/lib/docker/cli-plugins so this package never collides with (or -# gets silently shadowed by) a genuine Docker installation's own compose -# plugin on hosts that also run Unraid's built-in Docker support. -# ============================================================================= - -set -eu - -REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -# shellcheck source=/dev/null -. "$REPO_ROOT/scripts/lib/slackbuild-common.sh" -# shellcheck source=/dev/null -. "$REPO_ROOT/versions.env" - -VERSION="$DOCKER_COMPOSE_VERSION" -ARCH="$PKG_ARCH" -BUILD="$PKG_BUILD" -TAG="$PKG_TAG" - -sb_init "docker-compose" - -binary=$(sb_fetch_and_verify "$DOCKER_COMPOSE_SRC_URL" "$DOCKER_COMPOSE_SRC_SHA256" "docker-compose-$VERSION") - -install -D -m 0755 "$binary" "$PKG/usr/local/lib/docker/cli-plugins/docker-compose" - -# The release only ships the raw binary (+ checksum/signature files, no -# LICENSE/README asset) — write minimal doc metadata by hand instead of -# using sb_install_docs, which expects real files to copy from disk. -docdir="$PKG/usr/doc/docker-compose-$VERSION" -mkdir -p "$docdir" -{ - echo "docker-compose (docker/compose v2 CLI plugin) $VERSION" - echo "https://github.com/docker/compose" - echo "Prebuilt static binary, packaged as-is by unraid-podman — see" - echo "versions.env for the pinned release URL and SHA256." -} > "$docdir/README" -{ - echo "Built by unraid-podman from upstream's prebuilt release binary." - echo "Package: docker-compose $VERSION" - echo "Built: $(date -u +%Y-%m-%dT%H:%M:%SZ)" -} > "$docdir/unraid-podman.build-info" - -sb_make_package "$VERSION" "$ARCH" "$BUILD" "$TAG" diff --git a/packages/docker-compose/slack-desc b/packages/docker-compose/slack-desc deleted file mode 100644 index d75f979..0000000 --- a/packages/docker-compose/slack-desc +++ /dev/null @@ -1,19 +0,0 @@ -# HOW TO EDIT THIS FILE: -# The "handy ruler" below makes it easier to edit a package description. -# Line up the first '|' above the ':' following the base package name, and -# the '|' on the right side marks the last column you can put a character in. -# You must make exactly 11 lines for the formatting to be correct. It's also -# customary to leave one space after the ':' except on otherwise blank lines. - - |-----handy-ruler------------------------------------------------| -docker-compose: docker-compose (external Compose provider for podman compose) -docker-compose: -docker-compose: The docker/compose v2 CLI-plugin binary, installed as a -docker-compose: CLI-plugin so `podman compose` can find it. Required by the -docker-compose: WebUI's Compose panel; packaged from upstream's prebuilt -docker-compose: static binary release, not built from source. -docker-compose: -docker-compose: Homepage: https://github.com/docker/compose -docker-compose: -docker-compose: -docker-compose: diff --git a/packages/podman-compose/README.md b/packages/podman-compose/README.md new file mode 100644 index 0000000..c32b1cb --- /dev/null +++ b/packages/podman-compose/README.md @@ -0,0 +1,34 @@ +# packages/podman-compose/ + +Pinned versions: see `PODMAN_COMPOSE_VERSION`/`PYYAML_VERSION`/ +`PYTHON_DOTENV_VERSION` in [versions.env](../../versions.env). + +`podman compose` (backing `webui/plugins/podman/ajax/compose.php`, the +WebUI's Compose panel) has no compose implementation of its own — it +needs an external "compose provider" command. This project previously +vendored `docker/compose` (the Go CLI-plugin binary) for that role; +this package replaces it with `podman-compose` instead. + +The two aren't discovered the same way — verified live against a real +podman install (placing a fake executable and reading podman's own +provider-search error output): `docker-compose` is searched for by exact +path across a fixed list of CLI-plugin directories, while `podman-compose` +is looked up as a plain command on `$PATH`. That's why this package +installs to `/usr/local/bin/podman-compose` rather than under any +`cli-plugins/` directory. + +Unlike `docker-compose`, `podman-compose` is a single Python script, not a +compiled binary. Unraid ships Python3 itself but neither of its two +runtime dependencies, so this package also vendors: + +- `PyYAML` — only the pure-Python `yaml/` package, not the `_yaml` C + extension (which would need libyaml plus a compiler). `yaml/__init__.py` + falls back gracefully when the C accelerator isn't importable, so the + pure-Python source is sufficient for what podman-compose needs from it. +- `python-dotenv` — pure Python throughout, no C extensions at all. + +Verified end-to-end on a real Unraid host: the vendored bundle correctly +runs `podman compose up`/`ps`/`down` against a real compose project +(with the pre-existing `docker-compose` binary temporarily moved aside +to confirm `podman-compose` was the one actually being invoked, not a +leftover), including a live HTTP check against the started service. diff --git a/packages/podman-compose/podman-compose.SlackBuild b/packages/podman-compose/podman-compose.SlackBuild new file mode 100644 index 0000000..fd54031 --- /dev/null +++ b/packages/podman-compose/podman-compose.SlackBuild @@ -0,0 +1,83 @@ +#!/bin/bash +# ============================================================================= +# packages/podman-compose/podman-compose.SlackBuild +# +# Packages podman-compose (github.com/containers/podman-compose) — the +# external "compose provider" `podman compose` shells out to (see +# versions.env's PODMAN_COMPOSE_* block for the full story, including why +# this replaces the project's earlier vendored docker-compose). Verified +# live against a real podman install that podman-compose is looked up as a +# plain $PATH command, unlike docker-compose's fixed CLI-plugin-directory +# search — so this installs a wrapper at /usr/local/bin/podman-compose. +# +# podman-compose itself is a single Python script (not a compiled binary), +# with two runtime dependencies — PyYAML and python-dotenv — vendored here +# as plain pure-Python source (no C extension build) since Unraid ships +# Python3 but neither of those modules. +# ============================================================================= + +set -eu + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +# shellcheck source=/dev/null +. "$REPO_ROOT/scripts/lib/slackbuild-common.sh" +# shellcheck source=/dev/null +. "$REPO_ROOT/versions.env" + +VERSION="$PODMAN_COMPOSE_VERSION" +ARCH="$PKG_ARCH" +BUILD="$PKG_BUILD" +TAG="$PKG_TAG" + +sb_init "podman-compose" + +script=$(sb_fetch_and_verify "$PODMAN_COMPOSE_SRC_URL" "$PODMAN_COMPOSE_SRC_SHA256" "podman_compose-$VERSION.py") +pyyaml_tarball=$(sb_fetch_and_verify "$PYYAML_SRC_URL" "$PYYAML_SRC_SHA256" "pyyaml-$PYYAML_VERSION.tar.gz") +dotenv_tarball=$(sb_fetch_and_verify "$PYTHON_DOTENV_SRC_URL" "$PYTHON_DOTENV_SRC_SHA256" "python-dotenv-$PYTHON_DOTENV_VERSION.tar.gz") + +libdir="$PKG/usr/local/lib/podman-compose" +mkdir -p "$libdir" +install -m 0644 "$script" "$libdir/podman_compose.py" + +# Only the pure-Python "yaml" package, not the "_yaml" C extension (which +# would need libyaml plus a compiler toolchain this build doesn't otherwise +# require) — see the header comment on why the pure-Python fallback is +# sufficient for what podman-compose actually needs from it. +tar -xzf "$pyyaml_tarball" -C "$TMP" "pyyaml-$PYYAML_VERSION/lib/yaml" +cp -r "$TMP/pyyaml-$PYYAML_VERSION/lib/yaml" "$libdir/yaml" + +tar -xzf "$dotenv_tarball" -C "$TMP" "python_dotenv-$PYTHON_DOTENV_VERSION/src/dotenv" +cp -r "$TMP/python_dotenv-$PYTHON_DOTENV_VERSION/src/dotenv" "$libdir/dotenv" + +# A thin wrapper, not a symlink or bare shebang: podman_compose.py's own +# shebang (whatever upstream wrote, a plain "#!/usr/bin/env python3") has +# no idea the vendored yaml/dotenv sit right next to it, so PYTHONPATH has +# to be set by whatever actually invokes the script. +install -d "$PKG/usr/local/bin" +cat > "$PKG/usr/local/bin/podman-compose" <<'WRAPPER' +#!/bin/sh +exec env PYTHONPATH="/usr/local/lib/podman-compose${PYTHONPATH:+:$PYTHONPATH}" \ + /usr/bin/python3 /usr/local/lib/podman-compose/podman_compose.py "$@" +WRAPPER +chmod 0755 "$PKG/usr/local/bin/podman-compose" + +docdir="$PKG/usr/doc/podman-compose-$VERSION" +mkdir -p "$docdir" +{ + echo "podman-compose $VERSION" + echo "https://github.com/containers/podman-compose" + echo + echo "Vendored alongside its two runtime dependencies (bundled as plain" + echo "pure-Python source, no C extensions built):" + echo " PyYAML $PYYAML_VERSION - https://pypi.org/project/PyYAML/" + echo " python-dotenv $PYTHON_DOTENV_VERSION - https://pypi.org/project/python-dotenv/" + echo + echo "See versions.env for pinned source URLs and SHA256 checksums." +} > "$docdir/README" +{ + echo "Built by unraid-podman from upstream source." + echo "Package: podman-compose $VERSION" + echo "Built: $(date -u +%Y-%m-%dT%H:%M:%SZ)" +} > "$docdir/unraid-podman.build-info" + +sb_make_package "$VERSION" "$ARCH" "$BUILD" "$TAG" diff --git a/packages/podman-compose/slack-desc b/packages/podman-compose/slack-desc new file mode 100644 index 0000000..ef88b39 --- /dev/null +++ b/packages/podman-compose/slack-desc @@ -0,0 +1,19 @@ +# HOW TO EDIT THIS FILE: +# The "handy ruler" below makes it easier to edit a package description. +# Line up the first '|' above the ':' following the base package name, and +# the '|' on the right side marks the last column you can put a character in. +# You must make exactly 11 lines for the formatting to be correct. It's also +# customary to leave one space after the ':' except on otherwise blank lines. + + |-----handy-ruler------------------------------------------------| +podman-compose: podman-compose (external Compose provider for podman compose) +podman-compose: +podman-compose: A Python script that implements Docker Compose file support +podman-compose: on top of podman, installed to /usr/local/bin so +podman-compose: `podman compose` finds it as its external provider. +podman-compose: Required by the WebUI's Compose panel. Bundled with its +podman-compose: two runtime dependencies (PyYAML, python-dotenv) as plain +podman-compose: pure-Python source. +podman-compose: +podman-compose: Homepage: https://github.com/containers/podman-compose +podman-compose: diff --git a/plugin/podman.plg b/plugin/podman.plg index ca935bf..fc742ce 100644 --- a/plugin/podman.plg +++ b/plugin/podman.plg @@ -33,7 +33,7 @@ Structure of this file: 1. DOCTYPE entity block — plugin metadata + one version/file/md5 triple per package (the seven upstream components, catatonit/nftables/ - docker-compose as vendored runtime dependencies, plus this + podman-compose as vendored runtime dependencies, plus this project's own "unraid-podman" scaffolding package, see packages/unraid-podman/). Entities are rewritten automatically by scripts/release.sh; never @@ -122,12 +122,12 @@ - - - - + + +