mirror of
https://github.com/armbian/build
synced 2025-09-24 19:47:06 +07:00
armbian-next: mountpoints.sh with all bind/volume directories definitions and looping func; use it to determine best bind/volume combination for each host OS in Docker
This commit is contained in:
@@ -256,24 +256,6 @@ function docker_cli_build_dockerfile() {
|
||||
}
|
||||
|
||||
function docker_cli_prepare_launch() {
|
||||
# array for the generic armbian 'volumes' and their paths. Less specific first.
|
||||
# @TODO: actually use this for smth.
|
||||
declare -A -g DOCKER_ARMBIAN_VOLUMES=(
|
||||
[".tmp"]="linux=anonymous darwin=anonymous" # tmpfs, discard, anonymous; whatever you wanna call it. It just needs to be 100% local to the container, and there's very little value in being able to look at it from the host.
|
||||
["output"]="linux=bind darwin=bind" # catch-all output. specific subdirs are mounted below. it's a bind mount by default on both Linux and Darwin.
|
||||
["output/images"]="linux=bind darwin=bind" # 99% of users want this as the result of their build, no matter if it's slow or not. bind on both.
|
||||
["output/debs"]="linux=bind darwin=namedvolume" # generated output .deb files. not everyone is interested in this: most users just want images. Linux has fast binds, so bound by default. Darwin has slow binds, so it's a volume by default.
|
||||
["output/logs"]="linux=bind darwin=bind" # log files produced. 100% of users want this. Bind on both Linux and Darwin. Is used to integrate launcher and actual-build logs, so must exist and work otherwise confusion ensues.
|
||||
["cache"]="linux=bind darwin=namedvolume" # catch-all cache, could be bind-mounted or a volume. On Darwin it's too slow to bind-mount, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
["cache/gitballs"]="linux=bind darwin=namedvolume" # tarballs of git repos, can be bind-mounted or a volume. On Darwin it's too slow to bind-mount, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
["cache/toolchain"]="linux=bind darwin=namedvolume" # toolchain cache, can be bind-mounted or a volume. On Darwin it's too slow to bind-mount, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
["cache/aptcache"]="linux=bind darwin=namedvolume" # .deb apt cache, replaces apt-cacher-ng. Can be bind-mounted or a volume. On Darwin it's too slow to bind-mount, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
["cache/rootfs"]="linux=bind darwin=namedvolume" # rootfs .tar.zst cache, can be bind-mounted or a volume. On Darwin it's too slow to bind-mount, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
["cache/initrd"]="linux=bind darwin=namedvolume" # initrd.img cache, can be bind-mounted or a volume. On Darwin it's too slow to bind-mount, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
["cache/sources"]="linux=bind darwin=namedvolume" # operating directory. many things are cloned in here, and some are even built inside. needs to be local to the container, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
["cache/sources/linux-kernel"]="linux=bind darwin=namedvolume" # working tree for kernel builds. huge. contains both sources and the built object files. needs to be local to the container, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
)
|
||||
|
||||
display_alert "Preparing" "common Docker arguments" "debug"
|
||||
declare -g -a DOCKER_ARGS=(
|
||||
"--rm" # side effect - named volumes are considered not attached to anything and are removed on "docker volume prune", since container was removed.
|
||||
@@ -283,38 +265,52 @@ function docker_cli_prepare_launch() {
|
||||
"--cap-add=MKNOD" # (though MKNOD should be already present)
|
||||
"--cap-add=SYS_PTRACE" # CAP_SYS_PTRACE is required for systemd-detect-virt in some cases @TODO: rpardini: so lets eliminate it
|
||||
|
||||
# "--mount" "type=bind,source=${SRC}/lib,target=${DOCKER_ARMBIAN_TARGET_PATH}/lib"
|
||||
|
||||
# type=volume, without source=, is an anonymous volume -- will be auto cleaned up together with the container;
|
||||
# this could also be a type=tmpfs if you had enough ram - but armbian already does tmpfs for you if you
|
||||
# have enough RAM (inside the container) so don't bother.
|
||||
"--mount" "type=volume,destination=${DOCKER_ARMBIAN_TARGET_PATH}/.tmp"
|
||||
|
||||
# named volumes for different parts of the cache. so easy for user to drop any of them when needed
|
||||
# @TODO: refactor this; this is only ideal for Darwin right now. Use DOCKER_ARMBIAN_VOLUMES to generate this.
|
||||
"--mount" "type=volume,source=armbian-cache-parent,destination=${DOCKER_ARMBIAN_TARGET_PATH}/cache"
|
||||
"--mount" "type=volume,source=armbian-cache-gitballs,destination=${DOCKER_ARMBIAN_TARGET_PATH}/cache/gitballs"
|
||||
"--mount" "type=volume,source=armbian-cache-toolchain,destination=${DOCKER_ARMBIAN_TARGET_PATH}/cache/toolchain"
|
||||
"--mount" "type=volume,source=armbian-cache-aptcache,destination=${DOCKER_ARMBIAN_TARGET_PATH}/cache/aptcache"
|
||||
"--mount" "type=volume,source=armbian-cache-rootfs,destination=${DOCKER_ARMBIAN_TARGET_PATH}/cache/rootfs"
|
||||
"--mount" "type=volume,source=armbian-cache-initrd,destination=${DOCKER_ARMBIAN_TARGET_PATH}/cache/initrd"
|
||||
"--mount" "type=volume,source=armbian-cache-sources,destination=${DOCKER_ARMBIAN_TARGET_PATH}/cache/sources"
|
||||
"--mount" "type=volume,source=armbian-cache-sources-linux-kernel,destination=${DOCKER_ARMBIAN_TARGET_PATH}/cache/sources/linux-kernel"
|
||||
|
||||
# Pass env var ARMBIAN_RUNNING_IN_CONTAINER to indicate we're running under Docker. This is also set in the Dockerfile; make sure.
|
||||
"--env" "ARMBIAN_RUNNING_IN_CONTAINER=yes"
|
||||
|
||||
# @TODO: if user on terminal, pass the TERM down to the container.
|
||||
"--env" "TERM=${TERM}"
|
||||
# @TODO: pass down the CI-related env vars.
|
||||
)
|
||||
|
||||
# @TODO: auto-compute this list; just get the dirs and filter some out
|
||||
for MOUNT_DIR in "lib" "config" "extensions" "packages" "patch" "tools" "userpatches" "output"; do
|
||||
# This will receive the mountpoint as $1 and the mountpoint vars in the environment.
|
||||
function prepare_docker_args_for_mountpoint() {
|
||||
local MOUNT_DIR="$1"
|
||||
# shellcheck disable=SC2154 # $docker_kind: the kind of volume to mount on this OS; see mountpoints.sh
|
||||
#display_alert "Handling Docker mountpoint" "${MOUNT_DIR} id: ${volume_id} - docker_kind: ${docker_kind}" "debug"
|
||||
|
||||
case "${docker_kind}" in
|
||||
anonymous)
|
||||
display_alert "Mounting" "anonymous volume for '${MOUNT_DIR}'" "debug"
|
||||
# type=volume, without source=, is an anonymous volume -- will be auto cleaned up together with the container;
|
||||
# this could also be a type=tmpfs if you had enough ram - but armbian already does tmpfs for you if you
|
||||
# have enough RAM (inside the container) so don't bother.
|
||||
DOCKER_ARGS+=("--mount" "type=volume,destination=${DOCKER_ARMBIAN_TARGET_PATH}/${MOUNT_DIR}")
|
||||
;;
|
||||
bind)
|
||||
display_alert "Mounting" "bind mount for '${MOUNT_DIR}'" "debug"
|
||||
mkdir -p "${SRC}/${MOUNT_DIR}"
|
||||
DOCKER_ARGS+=("--mount" "type=bind,source=${SRC}/${MOUNT_DIR},target=${DOCKER_ARMBIAN_TARGET_PATH}/${MOUNT_DIR}")
|
||||
;;
|
||||
namedvolume)
|
||||
display_alert "Mounting" "named volume id '${volume_id}' for '${MOUNT_DIR}'" "debug"
|
||||
DOCKER_ARGS+=("--mount" "type=volume,source=armbian-${volume_id},destination=${DOCKER_ARMBIAN_TARGET_PATH}/${MOUNT_DIR}")
|
||||
;;
|
||||
*)
|
||||
display_alert "Unknown Mountpoint Type" "unknown volume type '${docker_kind}' for '${MOUNT_DIR}'" "err"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
loop_over_armbian_mountpoints prepare_docker_args_for_mountpoint
|
||||
|
||||
# @TODO: auto-compute this list; just get the dirs and filter some out?
|
||||
for MOUNT_DIR in "lib" "config" "extensions" "packages" "patch" "tools" "userpatches"; do
|
||||
mkdir -p "${SRC}/${MOUNT_DIR}"
|
||||
DOCKER_ARGS+=("--mount" "type=bind,source=${SRC}/${MOUNT_DIR},target=${DOCKER_ARMBIAN_TARGET_PATH}/${MOUNT_DIR}")
|
||||
done
|
||||
|
||||
# eg: NOT on Darwin with Docker Desktop, that works simply with --priviledged and the extra caps.
|
||||
# those actually _break_ Darwin with Docker Desktop, so we need to detect that.
|
||||
# 20/Oct/2022: trying with Rancher Desktop in dockerd mode on Mac M1, this is required; also loops have to be hardcoded.
|
||||
# How to detect this? It's Darwin, but not "real" Docker. How to find out?
|
||||
if [[ "${DOCKER_SERVER_REQUIRES_LOOP_HACKS}" == "yes" ]]; then
|
||||
display_alert "Adding /dev/loop* hacks for" "${DOCKER_ARMBIAN_HOST_OS_UNAME}" "debug"
|
||||
DOCKER_ARGS+=("--security-opt=apparmor:unconfined") # mounting things inside the container on Ubuntu won't work without this https://github.com/moby/moby/issues/16429#issuecomment-217126586
|
||||
@@ -345,6 +341,7 @@ function docker_cli_launch() {
|
||||
|
||||
display_alert "Relaunching in Docker" "${*}" "debug"
|
||||
display_alert "Relaunching in Docker" "here comes the 🐳" "info"
|
||||
|
||||
local -i docker_build_result=1
|
||||
if docker run -it "${DOCKER_ARGS[@]}" "${DOCKER_ARMBIAN_INITIAL_IMAGE_TAG}" /bin/bash "${DOCKER_ARMBIAN_TARGET_PATH}/compile.sh" "$@"; then
|
||||
display_alert "Docker Build finished" "successfully" "info"
|
||||
|
||||
66
lib/functions/host/mountpoints.sh
Normal file
66
lib/functions/host/mountpoints.sh
Normal file
@@ -0,0 +1,66 @@
|
||||
function prepare_armbian_mountpoints_description_dict() {
|
||||
# array for the generic armbian 'volumes' and their paths.
|
||||
# bash dicts do NOT keep their insertion order, instead "hash order", which is a bit better than random for our purposes.
|
||||
# keep an array with the correct order, unfortunately
|
||||
declare -g -a ARMBIAN_MOUNTPOINTS_ARRAY=(
|
||||
".tmp"
|
||||
"output" "output/images" "output/debs" "output/logs"
|
||||
"cache" "cache/gitballs" "cache/toolchain"
|
||||
"cache/aptcache"
|
||||
"cache/rootfs" "cache/initrd"
|
||||
"cache/sources" "cache/sources/linux-kernel"
|
||||
)
|
||||
|
||||
declare -A -g ARMBIAN_MOUNTPOINTS_DESC_DICT=(
|
||||
[".tmp"]="docker_kind_linux=anonymous docker_kind_darwin=anonymous" # tmpfs, discard, anonymous; whatever you wanna call it. It just needs to be 100% local to the container, and there's very little value in being able to look at it from the host.
|
||||
["output"]="docker_kind_linux=bind docker_kind_darwin=bind" # catch-all output. specific subdirs are mounted below. it's a bind mount by default on both Linux and Darwin.
|
||||
["output/images"]="docker_kind_linux=bind docker_kind_darwin=bind" # 99% of users want this as the result of their build, no matter if it's slow or not. bind on both.
|
||||
["output/debs"]="docker_kind_linux=bind docker_kind_darwin=namedvolume" # generated output .deb files. not everyone is interested in this: most users just want images. Linux has fast binds, so bound by default. Darwin has slow binds, so it's a volume by default.
|
||||
["output/logs"]="docker_kind_linux=bind docker_kind_darwin=bind" # log files produced. 100% of users want this. Bind on both Linux and Darwin. Is used to integrate launcher and actual-build logs, so must exist and work otherwise confusion ensues.
|
||||
["cache"]="docker_kind_linux=bind docker_kind_darwin=namedvolume" # catch-all cache, could be bind-mounted or a volume. On Darwin it's too slow to bind-mount, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
["cache/gitballs"]="docker_kind_linux=bind docker_kind_darwin=namedvolume" # tarballs of git repos, can be bind-mounted or a volume. On Darwin it's too slow to bind-mount, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
["cache/toolchain"]="docker_kind_linux=bind docker_kind_darwin=namedvolume" # toolchain cache, can be bind-mounted or a volume. On Darwin it's too slow to bind-mount, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
["cache/aptcache"]="docker_kind_linux=bind docker_kind_darwin=namedvolume" # .deb apt cache, replaces apt-cacher-ng. Can be bind-mounted or a volume. On Darwin it's too slow to bind-mount, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
["cache/rootfs"]="docker_kind_linux=bind docker_kind_darwin=namedvolume" # rootfs .tar.zst cache, can be bind-mounted or a volume. On Darwin it's too slow to bind-mount, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
["cache/initrd"]="docker_kind_linux=bind docker_kind_darwin=namedvolume" # initrd.img cache, can be bind-mounted or a volume. On Darwin it's too slow to bind-mount, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
["cache/sources"]="docker_kind_linux=bind docker_kind_darwin=namedvolume" # operating directory. many things are cloned in here, and some are even built inside. needs to be local to the container, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
["cache/sources/linux-kernel"]="docker_kind_linux=bind docker_kind_darwin=namedvolume" # working tree for kernel builds. huge. contains both sources and the built object files. needs to be local to the container, so it's a volume by default. On Linux, it's a bind-mount by default.
|
||||
)
|
||||
}
|
||||
|
||||
function loop_over_armbian_mountpoints() {
|
||||
prepare_armbian_mountpoints_description_dict
|
||||
# loop over all mountpoints and call the function passed as first argument
|
||||
: "${1:?loop_over_mountpoints needs a function as first argument}"
|
||||
local func="$1"
|
||||
shift
|
||||
local mountpoint
|
||||
for mountpoint in "${ARMBIAN_MOUNTPOINTS_ARRAY[@]}"; do
|
||||
# call func passing the key and the values as arguments
|
||||
local values="${ARMBIAN_MOUNTPOINTS_DESC_DICT[$mountpoint]}"
|
||||
eval "$values"
|
||||
|
||||
# This is contrived. Would be easier to just eval (and use Linux/Darwin instead of linux/darwin)
|
||||
declare docker_kind="unknown"
|
||||
case "${DOCKER_ARMBIAN_HOST_OS_UNAME}" in
|
||||
Linux)
|
||||
# shellcheck disable=SC2154 # defined during loop_over_armbian_mountpoints
|
||||
docker_kind="${docker_kind_linux}"
|
||||
;;
|
||||
|
||||
Darwin)
|
||||
# shellcheck disable=SC2154 # defined during loop_over_armbian_mountpoints
|
||||
docker_kind="${docker_kind_darwin}"
|
||||
;;
|
||||
*)
|
||||
display_alert "Unsupported host OS" "${DOCKER_ARMBIAN_HOST_OS_UNAME} - cant map mountpoint to Docker volume" "warn"
|
||||
;;
|
||||
esac
|
||||
|
||||
# volume_id is the mountpoint with all slashes replaced with dashes
|
||||
local volume_id="${mountpoint//\//-}"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
eval "$values docker_kind=$docker_kind $func '$mountpoint'"
|
||||
done
|
||||
}
|
||||
@@ -361,6 +361,15 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true
|
||||
# shellcheck source=lib/functions/host/host-utils.sh
|
||||
source "${SRC}"/lib/functions/host/host-utils.sh
|
||||
|
||||
# no errors tolerated. invoked before each sourced file to make sure.
|
||||
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
||||
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
|
||||
set -o errtrace # trace ERR through - enabled
|
||||
set -o errexit ## set -e : exit the script if any statement returns a non-true return value - enabled
|
||||
### lib/functions/host/mountpoints.sh
|
||||
# shellcheck source=lib/functions/host/mountpoints.sh
|
||||
source "${SRC}"/lib/functions/host/mountpoints.sh
|
||||
|
||||
# no errors tolerated. invoked before each sourced file to make sure.
|
||||
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
||||
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
|
||||
|
||||
Reference in New Issue
Block a user