Skip to content

Commit 6e7e103

Browse files
committed
RFCv2: Add support for Podman as container engine alternative to Docker
This RFC implements Podman support for Armbian builds to address mounting issues experienced with Podman while maintaining Docker compatibility. Key changes: - Auto-detect container engine: prefers Docker, falls back to Podman - Use sudo with Podman (runs in root mode - not more secure than Docker) - Add required mount options (suid,dev) and --network host for Podman - Update all docker commands to use dynamic DOCKER_COMMAND variable Technical notes: - Podman runs with sudo/root privileges, so security model matches Docker - Requires sudo access when using Podman (security consideration) - Solves Podman-specific mount permission and networking issues - Maintains full backward compatibility with existing Docker workflows - May need documentation updates
1 parent 5c273e2 commit 6e7e103

File tree

1 file changed

+33
-20
lines changed

1 file changed

+33
-20
lines changed

lib/functions/host/docker.sh

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,35 @@ function get_docker_info_once() {
4242
if [[ -z "${DOCKER_INFO}" ]]; then
4343
declare -g DOCKER_INFO
4444
declare -g DOCKER_IN_PATH="no"
45-
46-
# if "docker" is in the PATH...
45+
declare -g DOCKER_COMMAND="docker"
46+
declare -g DOCKER_NETWORK=""
47+
declare -g DOCKER_MOUNT_OPTS=""
48+
49+
# Detect container engine - prefer Docker for compatibility, but support Podman
4750
if [[ -n "$(command -v docker)" ]]; then
4851
display_alert "Docker is in the path" "Docker in PATH" "debug"
52+
DOCKER_COMMAND="docker"
53+
display_alert "Docker detected" "Using Docker" "debug"
4954
DOCKER_IN_PATH="yes"
55+
elif [[ -n "$(command -v podman)" ]]; then
56+
DOCKER_COMMAND="sudo podman"
57+
DOCKER_NETWORK="--network host"
58+
DOCKER_MOUNT_OPTS=",suid,dev" # Required mount options for Podman
59+
display_alert "Podman detected" "Using Podman with sudo (required for Armbian builds)" "info"
5060
fi
5161

5262
# Shenanigans to go around error control & capture output in the same effort.
53-
DOCKER_INFO="$({ docker info 2> /dev/null && echo "DOCKER_INFO_OK"; } || true)"
63+
DOCKER_INFO="$({ $DOCKER_COMMAND info 2> /dev/null && echo "DOCKER_INFO_OK"; } || true)"
5464
declare -g -r DOCKER_INFO="${DOCKER_INFO}" # readonly
5565

5666
declare -g DOCKER_INFO_OK="no"
5767
if [[ "${DOCKER_INFO}" =~ "DOCKER_INFO_OK" ]]; then
5868
DOCKER_INFO_OK="yes"
5969
fi
6070
declare -g -r DOCKER_INFO_OK="${DOCKER_INFO_OK}" # readonly
71+
declare -g -r DOCKER_COMMAND="${DOCKER_COMMAND}"
72+
declare -g -r DOCKER_NETWORK="${DOCKER_NETWORK}"
73+
declare -g -r DOCKER_MOUNT_OPTS="${DOCKER_MOUNT_OPTS}"
6174
fi
6275
return 0
6376
}
@@ -73,8 +86,8 @@ function is_docker_ready_to_go() {
7386
display_alert "Can't use Docker" "Actually ALREADY UNDER DOCKER!" "debug"
7487
return 1
7588
fi
76-
if [[ -z "$(command -v docker)" ]]; then
77-
display_alert "Can't use Docker" "docker command not found" "debug"
89+
if [[ -z "$(command -v docker)" ]] && [[ -z "$(command -v podman)" ]]; then
90+
display_alert "Can't use Docker" "docker or podman command not found" "debug"
7891
return 1
7992
fi
8093

@@ -97,19 +110,19 @@ function cli_handle_docker() {
97110
# Purge Armbian Docker images
98111
if [[ "${1}" == dockerpurge && -f /etc/debian_version ]]; then
99112
display_alert "Purging Armbian Docker containers" "" "wrn"
100-
docker container ls -a | grep armbian | awk '{print $1}' | xargs docker container rm &> /dev/null
101-
docker image ls | grep armbian | awk '{print $3}' | xargs docker image rm &> /dev/null
113+
$DOCKER_COMMAND container ls -a | grep armbian | awk '{print $1}' | xargs $DOCKER_COMMAND container rm &> /dev/null
114+
$DOCKER_COMMAND image ls | grep armbian | awk '{print $3}' | xargs $DOCKER_COMMAND image rm &> /dev/null
102115
# removes "dockerpurge" from $1, thus $2 becomes $1
103116
shift
104-
set -- "docker" "$@"
117+
set -- $DOCKER_COMMAND "$@"
105118
fi
106119

107120
# Docker shell
108121
if [[ "${1}" == docker-shell ]]; then
109122
# this swaps the value of $1 with 'docker', and life continues
110123
shift
111124
SHELL_ONLY=yes
112-
set -- "docker" "$@"
125+
set -- $DOCKER_COMMAND "$@"
113126
fi
114127

115128
}
@@ -323,7 +336,7 @@ function docker_cli_build_dockerfile() {
323336

324337
if [[ "${do_force_pull}" == "no" ]]; then
325338
# Check if the base image is up to date.
326-
local_image_sha="$(docker images --no-trunc --quiet "${DOCKER_ARMBIAN_BASE_IMAGE}")"
339+
local_image_sha="$($DOCKER_COMMAND images --no-trunc --quiet "${DOCKER_ARMBIAN_BASE_IMAGE}")"
327340
display_alert "Checking if base image exists at all" "local_image_sha: '${local_image_sha}'" "debug"
328341
if [[ -n "${local_image_sha}" ]]; then
329342
display_alert "Armbian docker image" "already exists: ${DOCKER_ARMBIAN_BASE_IMAGE}" "info"
@@ -336,10 +349,10 @@ function docker_cli_build_dockerfile() {
336349
if [[ "${do_force_pull:-yes}" == "yes" ]]; then
337350
display_alert "Pulling" "${DOCKER_ARMBIAN_BASE_IMAGE}" "info"
338351
local pull_failed="yes"
339-
run_host_command_logged docker pull "${DOCKER_ARMBIAN_BASE_IMAGE}" && pull_failed="no"
352+
run_host_command_logged $DOCKER_COMMAND pull "${DOCKER_ARMBIAN_BASE_IMAGE}" && pull_failed="no"
340353

341354
if [[ "${pull_failed}" == "no" ]]; then
342-
local_image_sha="$(docker images --no-trunc --quiet "${DOCKER_ARMBIAN_BASE_IMAGE}")"
355+
local_image_sha="$($DOCKER_COMMAND images --no-trunc --quiet "${DOCKER_ARMBIAN_BASE_IMAGE}")"
343356
display_alert "New local image sha after pull" "local_image_sha: ${local_image_sha}" "debug"
344357
# print current date and time in epoch format; touches mtime of file
345358
echo "${DOCKER_ARMBIAN_BASE_IMAGE}|${local_image_sha}|$(date +%s)" >> "${docker_marker_dir}"/last-pull
@@ -360,7 +373,7 @@ function docker_cli_build_dockerfile() {
360373
display_alert "Building" "Dockerfile via '${DOCKER_BUILDX_OR_BUILD[*]}'" "info"
361374

362375
BUILDKIT_COLORS="run=123,20,245:error=yellow:cancel=blue:warning=white" \
363-
run_host_command_logged docker "${DOCKER_BUILDX_OR_BUILD[@]}" -t "${DOCKER_ARMBIAN_INITIAL_IMAGE_TAG}" -f "${SRC}"/Dockerfile "${SRC}"
376+
run_host_command_logged $DOCKER_COMMAND "${DOCKER_BUILDX_OR_BUILD[@]}" -t "${DOCKER_ARMBIAN_INITIAL_IMAGE_TAG}" -f "${SRC}"/Dockerfile "${SRC}"
364377
}
365378

366379
function docker_cli_prepare_launch() {
@@ -503,16 +516,16 @@ function docker_cli_prepare_launch() {
503516
# type=volume, without source=, is an anonymous volume -- will be auto cleaned up together with the container;
504517
# this could also be a type=tmpfs if you had enough ram - but armbian already does tmpfs for you if you
505518
# have enough RAM (inside the container) so don't bother.
506-
DOCKER_ARGS+=("--mount" "type=volume,destination=${DOCKER_ARMBIAN_TARGET_PATH}/${MOUNT_DIR}")
519+
DOCKER_ARGS+=("--mount" "type=volume,destination=${DOCKER_ARMBIAN_TARGET_PATH}/${MOUNT_DIR}${DOCKER_MOUNT_OPTS}")
507520
;;
508521
bind)
509522
display_alert "Mounting" "bind mount for '${MOUNT_DIR}'" "debug"
510523
mkdir -p "${SRC}/${MOUNT_DIR}"
511-
DOCKER_ARGS+=("--mount" "type=bind,source=${SRC}/${MOUNT_DIR},target=${DOCKER_ARMBIAN_TARGET_PATH}/${MOUNT_DIR}")
524+
DOCKER_ARGS+=("--mount" "type=bind,source=${SRC}/${MOUNT_DIR},target=${DOCKER_ARMBIAN_TARGET_PATH}/${MOUNT_DIR}${DOCKER_MOUNT_OPTS}")
512525
;;
513526
namedvolume)
514527
display_alert "Mounting" "named volume id '${volume_id}' for '${MOUNT_DIR}'" "debug"
515-
DOCKER_ARGS+=("--mount" "type=volume,source=armbian-${volume_id},destination=${DOCKER_ARMBIAN_TARGET_PATH}/${MOUNT_DIR}")
528+
DOCKER_ARGS+=("--mount" "type=volume,source=armbian-${volume_id},destination=${DOCKER_ARMBIAN_TARGET_PATH}/${MOUNT_DIR}${DOCKER_MOUNT_OPTS}")
516529
;;
517530
*)
518531
display_alert "Unknown Mountpoint Type" "unknown volume type '${docker_kind}' for '${MOUNT_DIR}'" "err"
@@ -585,13 +598,13 @@ function docker_cli_launch() {
585598
# The amount of privileges and capabilities given is a bare minimum needed for losetup to work
586599
if [[ ! -e /dev/loop0 ]]; then
587600
display_alert "Running losetup in a temporary container" "because no loop devices exist" "info"
588-
run_host_command_logged docker run --rm --privileged --cap-add=MKNOD "${DOCKER_ARMBIAN_INITIAL_IMAGE_TAG}" /usr/sbin/losetup -f
601+
run_host_command_logged $DOCKER_COMMAND run $DOCKER_NETWORK --rm --privileged --cap-add=MKNOD "${DOCKER_ARMBIAN_INITIAL_IMAGE_TAG}" /usr/sbin/losetup -f
589602
fi
590603

591604
display_alert "-----------------Relaunching in Docker after ${SECONDS}s------------------" "here comes the 🐳" "info"
592605

593606
local -i docker_build_result
594-
if docker run "${DOCKER_ARGS[@]}" "${DOCKER_ARMBIAN_INITIAL_IMAGE_TAG}" /bin/bash "${DOCKER_ARMBIAN_TARGET_PATH}/compile.sh" "${ARMBIAN_CLI_FINAL_RELAUNCH_ARGS[@]}"; then
607+
if $DOCKER_COMMAND run $DOCKER_NETWORK "${DOCKER_ARGS[@]}" "${DOCKER_ARMBIAN_INITIAL_IMAGE_TAG}" /bin/bash "${DOCKER_ARMBIAN_TARGET_PATH}/compile.sh" "${ARMBIAN_CLI_FINAL_RELAUNCH_ARGS[@]}"; then
595608
docker_build_result=$? # capture exit code of test done in the line above.
596609
display_alert "-------------Docker run finished after ${SECONDS}s------------------------" "🐳 successful" "info"
597610
else
@@ -623,8 +636,8 @@ function docker_purge_deprecated_volumes() {
623636
for mountpoint in "${ARMBIAN_MOUNTPOINTS_DEPRECATED[@]}"; do
624637
local volume_id="armbian-${mountpoint//\//-}"
625638
display_alert "Purging deprecated Docker volume" "${volume_id}" "info"
626-
if docker volume inspect "${volume_id}" &> /dev/null; then
627-
run_host_command_logged docker volume rm "${volume_id}"
639+
if $DOCKER_COMMAND volume inspect "${volume_id}" &> /dev/null; then
640+
run_host_command_logged $DOCKER_COMMAND volume rm "${volume_id}"
628641
display_alert "Purged deprecated Docker volume" "${volume_id} OK" "info"
629642
else
630643
display_alert "Deprecated Docker volume not found" "${volume_id} OK" "info"

0 commit comments

Comments
 (0)