Support rootless Podman builds

This commit is contained in:
Ryan Hughes committed 2026-09-04 23:40:49 -04:00
1 parent 76687fcc82
commit 9e9acb071a
8 files changed
+198 -78

No files matched your search

+21 -10
View File
@@ -145,7 +145,7 @@ if [[ $DEFER_RUNTIME_DEPS == "true" ]]; then
fi
if [[ "$DRY_RUN" == true ]]; then
print_warning "DRY RUN MODE - build plan only; no Docker or makepkg will run"
print_warning "DRY RUN MODE - build plan only; no container or makepkg will run"
ARCH="$ARCH" \
MIRROR="$MIRROR" \
PACKAGES="$PACKAGES" \
@@ -163,8 +163,8 @@ fi
# Create directories if they don't exist
mkdir -p "$BUILD_OUTPUT_DIR" "$REPO_DIR" "$SRC_DIR"
# Check Docker is available
check_docker
# Check the selected container engine is available
check_engine
# A foreign target architecture runs under QEMU user emulation. Probe by
# actually running a container for the target platform: that is the only
@@ -172,9 +172,11 @@ check_docker
HOST_ARCH=$(uname -m)
[[ "$HOST_ARCH" == "arm64" ]] && HOST_ARCH=aarch64
if [[ "$HOST_ARCH" != "$ARCH" ]]; then
if ! docker run --rm "$(get_platform_arg "$ARCH")" alpine:3.21 /bin/true >/dev/null 2>&1; then
PROBE_IMAGE="alpine:3.21"
[[ "$CONTAINER_ENGINE" == "podman" ]] && PROBE_IMAGE="docker.io/library/alpine:3.21"
if ! "$CONTAINER_ENGINE" run "${CONTAINER_RUN_ARGS[@]}" --rm "$(get_platform_arg "$ARCH")" "$PROBE_IMAGE" /bin/true >/dev/null 2>&1; then
print_info "Setting up QEMU for $ARCH emulation on this $HOST_ARCH host..."
setup_qemu
setup_qemu "$ARCH"
fi
fi
@@ -201,7 +203,7 @@ fi
# flag is that every job runs the same bytes.
IMAGE_TAG="omarchy-pkg-builder:latest-$ARCH-$MIRROR"
if [[ $SKIP_BUILDER_IMAGE == "1" ]]; then
if ! docker image inspect "$IMAGE_TAG" >/dev/null 2>&1; then
if ! "$CONTAINER_ENGINE" image inspect "$IMAGE_TAG" >/dev/null 2>&1; then
print_error "Prepared builder image is unavailable: $IMAGE_TAG"
exit 1
fi
@@ -216,9 +218,12 @@ print_info "Running package build..."
mkdir -p "$BUILD_OUTPUT_DIR"
mkdir -p "$REPO_DIR"
# Ensure output directories are writable by container user
make_dir_writable "$BUILD_OUTPUT_DIR"
make_dir_writable "$REPO_DIR"
# Rootful Docker writes as the image uid, so retain its existing permission
# workaround. Rootless Podman uses keep-id and must leave ownership/modes alone.
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
make_dir_writable "$BUILD_OUTPUT_DIR"
make_dir_writable "$REPO_DIR"
fi
# Build Docker arguments
DOCKER_ARGS=(
@@ -235,10 +240,16 @@ DOCKER_ARGS=(
-v "$BUILD_ROOT/pkgbuilds:/pkgbuilds:ro"
)
# Podman-created images can leave WORKDIR owned by a remapped uid. Mount the
# existing host-user-owned workspace so the builder can write there.
if [[ "$CONTAINER_ENGINE" == "podman" ]]; then
DOCKER_ARGS+=(-v "$SRC_DIR:/src")
fi
# Run the builder with assembled args
PLATFORM_ARG=$(get_platform_arg "$ARCH")
docker run "$PLATFORM_ARG" "${DOCKER_ARGS[@]}" "$IMAGE_TAG" /build/build.sh
"$CONTAINER_ENGINE" run "${CONTAINER_RUN_ARGS[@]}" "$PLATFORM_ARG" "${DOCKER_ARGS[@]}" "$IMAGE_TAG" /build/build.sh
BUILD_RESULT=$?
+13 -7
View File
@@ -1,21 +1,27 @@
#!/bin/bash
# Clean Docker builder images and cache
# Clean builder images and cache for the selected container engine
# Forces a fresh image build on next run
set -e
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
source "$BUILD_ROOT/helpers/message-helpers.sh"
source "$BUILD_ROOT/helpers/docker-helpers.sh"
print_header "Cleaning Docker Builder Images"
check_engine
print_header "Cleaning Container Builder Images"
# Remove all omarchy-pkg-builder images
print_info "Removing omarchy-pkg-builder images..."
docker images omarchy-pkg-builder -q | xargs -r docker rmi -f 2>/dev/null || true
"$CONTAINER_ENGINE" images omarchy-pkg-builder -q | xargs -r "$CONTAINER_ENGINE" rmi -f 2>/dev/null || true
# Clear buildx cache for these builds
print_info "Clearing buildx cache..."
docker buildx prune -a -f
# Clear this engine's build cache.
print_info "Clearing build cache..."
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
"$CONTAINER_ENGINE" buildx prune -a -f
else
"$CONTAINER_ENGINE" image prune --build-cache -f
fi
print_success "Docker builder cache cleared"
print_success "Container builder cache cleared"
print_info "Next build will create fresh images"
+6 -5
View File
@@ -18,6 +18,7 @@ set -e
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
source "$BUILD_ROOT/helpers/message-helpers.sh"
source "$BUILD_ROOT/helpers/docker-helpers.sh"
source "$BUILD_ROOT/helpers/paths.sh"
source "$BUILD_ROOT/helpers/host-helpers.sh"
@@ -374,8 +375,8 @@ iso_checkout() { # prints a usable omarchy-iso checkout, cloning to tmp if neede
build_iso() { # build_iso <version> [--rc]
local version="$1" rc_flag="${2:-}" dir
dir=$(iso_checkout) || return 1
if ! command -v docker >/dev/null || ! docker info >/dev/null 2>&1; then
print_warning "Docker unavailable — cannot build the ISO here. Run on a Docker machine:"
if [[ -z "$CONTAINER_ENGINE" ]] || ! "$CONTAINER_ENGINE" info >/dev/null 2>&1; then
print_warning "No container engine is available — cannot build the ISO here. Run on a Docker or Podman machine:"
echo " cd $dir && bin/omarchy-iso-release ${rc_flag:+$rc_flag }$version"
return 1
fi
@@ -1034,10 +1035,10 @@ cmd_doctor() {
else
print_warning "no build host configured — set OMARCHY_REPO_HOST, --host, or write an ssh destination (root@<host> or an ssh-config alias) to $BUILD_ROOT/.repo-host; until then builds trigger on the 6h timer only"
fi
if command -v docker >/dev/null && docker info >/dev/null 2>&1; then
print_success "docker available (ISO builds possible here)"
if [[ -n "$CONTAINER_ENGINE" ]] && "$CONTAINER_ENGINE" info >/dev/null 2>&1; then
print_success "$CONTAINER_ENGINE available (ISO builds possible here)"
else
print_warning "docker unavailable — ISO builds will print instructions instead"
print_warning "container engine unavailable — ISO builds will print instructions instead"
fi
echo ""
if ((failures == 0)); then
+7 -5
View File
@@ -62,8 +62,8 @@ if [[ ! -d "$REPO_DIR" ]]; then
exit 1
fi
# Check Docker is available
check_docker
# Check the selected container engine is available
check_engine
# Find package files to confirm before running Docker
cd "$REPO_DIR"
@@ -99,11 +99,13 @@ acquire_release_lock || exit 1
print_info "Removing package..."
# Ensure directory is writable by container user
make_dir_writable "$REPO_DIR"
# Rootless Podman uses keep-id and leaves host ownership/modes intact.
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
make_dir_writable "$REPO_DIR"
fi
# Run the removal script in the host-native image.
docker run --rm "$(get_platform_arg "$TOOL_ARCH")" \
"$CONTAINER_ENGINE" run "${CONTAINER_RUN_ARGS[@]}" --rm "$(get_platform_arg "$TOOL_ARCH")" \
-e ARCH="$ARCH" \
-e MIRROR="$MIRROR" \
-v "$REPO_ROOT:/pkgs.omarchy.org" \
+54 -22
View File
@@ -15,6 +15,7 @@ set -e
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
source "$BUILD_ROOT/helpers/message-helpers.sh"
source "$BUILD_ROOT/helpers/docker-helpers.sh"
source "$BUILD_ROOT/helpers/paths.sh"
CHECK_ONLY=false
@@ -62,10 +63,12 @@ if command -v apt-get >/dev/null 2>&1; then
DISTRO="debian"
PKG_BSDTAR="libarchive-tools"
PKG_DOCKER="docker.io"
PKG_PODMAN="podman"
elif command -v pacman >/dev/null 2>&1; then
DISTRO="arch"
PKG_BSDTAR="libarchive"
PKG_DOCKER="docker"
PKG_PODMAN="podman"
else
print_error "Unsupported distribution — need apt-get or pacman"
exit 1
@@ -73,18 +76,36 @@ fi
print_info "Distribution: $DISTRO"
# A fresh repository host still defaults to Docker. An explicit Podman choice,
# or a working Podman selected by the shared helper, is left alone.
if [[ -z "$CONTAINER_ENGINE" ]]; then
CONTAINER_ENGINE=docker
export CONTAINER_ENGINE
fi
if ! container_engine_supported; then
print_error "Unsupported CONTAINER_ENGINE: $CONTAINER_ENGINE (use docker or podman)"
exit 1
fi
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
PKG_ENGINE="$PKG_DOCKER"
ENGINE_NAME="Docker"
else
PKG_ENGINE="$PKG_PODMAN"
ENGINE_NAME="Podman"
fi
if [[ "$CHECK_ONLY" != true && $EUID -ne 0 ]]; then
print_error "Run as root (installing packages and systemd units)"
exit 1
fi
# Docker and the release timers are both systemd units. Say so plainly rather
# than failing later on a missing command — a container is the usual way to end
# up here, and it cannot be a repository host.
# The release timers are systemd units. Say so plainly rather than failing
# later on a missing command — a container is the usual way to end up here,
# and it cannot be a repository host.
if [[ "$CHECK_ONLY" != true ]] && ! command -v systemctl >/dev/null 2>&1; then
print_error "systemctl not found — the repository host must run systemd"
echo ""
echo "Docker and the release timers are systemd units. This looks like a"
echo "The release timers are systemd units. This looks like a"
echo "container; run setup on the host itself."
exit 1
fi
@@ -140,24 +161,27 @@ else
fi
echo ""
# --- docker ------------------------------------------------------------------
# --- container engine --------------------------------------------------------
# Docker is left alone when it already works. A host may well be running a
# The selected engine is left alone when it already works. A host may be running a
# version from Docker's own repository rather than the distribution's, and
# replacing that underneath a working builder would be a poor trade for
# tidiness.
print_info "Checking Docker..."
print_info "Checking $ENGINE_NAME..."
if command -v docker >/dev/null 2>&1; then
print_step "docker present: $(docker --version 2>/dev/null | head -1)"
if docker info >/dev/null 2>&1; then
print_success "Docker is installed and running — leaving it alone"
if command -v "$CONTAINER_ENGINE" >/dev/null 2>&1; then
print_step "$CONTAINER_ENGINE present: $("$CONTAINER_ENGINE" --version 2>/dev/null | head -1)"
if "$CONTAINER_ENGINE" info >/dev/null 2>&1; then
print_success "$ENGINE_NAME is installed and available — leaving it alone"
elif [[ "$CHECK_ONLY" == true ]]; then
print_warning "Docker is installed but not running; would start it"
print_warning "$ENGINE_NAME is installed but unavailable"
elif [[ "$CONTAINER_ENGINE" == "podman" ]]; then
print_error "Podman is installed but unavailable to the current user"
exit 1
else
print_info "Docker is installed but not running — starting it"
systemctl enable --now docker.service
if docker info >/dev/null 2>&1; then
if "$CONTAINER_ENGINE" info >/dev/null 2>&1; then
print_success "Docker started"
else
print_error "Docker is installed but still not responding"
@@ -166,16 +190,24 @@ if command -v docker >/dev/null 2>&1; then
fi
fi
elif [[ "$CHECK_ONLY" == true ]]; then
print_warning "Would install $PKG_DOCKER and enable it"
else
print_info "Installing $PKG_DOCKER..."
install_packages "$PKG_DOCKER"
systemctl enable --now docker.service
if docker info >/dev/null 2>&1; then
print_success "Docker installed and running"
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
print_warning "Would install $PKG_ENGINE and enable it"
else
print_error "Docker installed but not responding"
echo " Check 'systemctl status docker' — builds cannot run without it."
print_warning "Would install $PKG_ENGINE"
fi
else
print_info "Installing $PKG_ENGINE..."
install_packages "$PKG_ENGINE"
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
systemctl enable --now docker.service
fi
if "$CONTAINER_ENGINE" info >/dev/null 2>&1; then
print_success "$ENGINE_NAME installed and available"
else
print_error "$ENGINE_NAME installed but not responding"
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
echo " Check 'systemctl status docker' — builds cannot run without it."
fi
exit 1
fi
fi
+7 -5
View File
@@ -52,8 +52,8 @@ if [[ ! -d "$BUILD_OUTPUT_DIR" ]]; then
exit 1
fi
# Check Docker is available
check_docker
# Check the selected container engine is available
check_engine
# Check GPG credentials are in environment
if [[ -z "$GPG_PRIVATE_KEY" ]]; then
@@ -76,11 +76,13 @@ build_docker_image "$BUILD_DIR" "$TOOL_ARCH" "$MIRROR"
print_info "Running package signing..."
# Ensure output directory is writable by container user
make_dir_writable "$BUILD_OUTPUT_DIR"
# Rootless Podman uses keep-id and leaves host ownership/modes intact.
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
make_dir_writable "$BUILD_OUTPUT_DIR"
fi
# Run the signing script in the host-native image.
docker run --rm "$(get_platform_arg "$TOOL_ARCH")" \
"$CONTAINER_ENGINE" run "${CONTAINER_RUN_ARGS[@]}" --rm "$(get_platform_arg "$TOOL_ARCH")" \
-e ARCH="$ARCH" \
-e MIRROR="$MIRROR" \
-e GPG_PRIVATE_KEY="$GPG_PRIVATE_KEY" \
+7 -7
View File
@@ -11,12 +11,11 @@ source "$BUILD_ROOT/helpers/docker-helpers.sh"
source "$BUILD_ROOT/helpers/paths.sh"
source "$BUILD_ROOT/helpers/lock-helpers.sh"
# Function to update repository database using Docker
# Function to update repository database using the selected container engine
update_database() {
print_info "Updating repository database in Docker container..."
print_info "Updating repository database in a container..."
# Check Docker is available
check_docker
check_engine
# Ensure output directory exists
if [[ ! -d "$REPO_DIR" ]]; then
@@ -25,8 +24,9 @@ update_database() {
exit 1
fi
# Make output directory writable for container
make_dir_writable "$REPO_DIR"
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
make_dir_writable "$REPO_DIR"
fi
# repo-add is architecture- and mirror-independent. Use the host-native edge
# image, which also lets bootstrap-rc run before that channel exists remotely.
@@ -37,7 +37,7 @@ update_database() {
}
build_docker_image "$BUILD_DIR" "$tool_arch" "edge"
docker run --rm "$(get_platform_arg "$tool_arch")" \
"$CONTAINER_ENGINE" run "${CONTAINER_RUN_ARGS[@]}" --rm "$(get_platform_arg "$tool_arch")" \
-e ARCH="$ARCH" \
-e MIRROR="$MIRROR" \
-v "$REPO_ROOT:/output" \