1#!/bin/bash -r 2 3function container_exists() { 4 [[ $(docker ps -a --filter "name=^/$1$" --format '{{.Names}}') == $1 ]] && echo $1; 5} 6 7declare -A map_uname_to_docker_builder_arch=( [aarch64]=linux/arm64 [x86_64]=linux/amd64 ) 8 9# inputs 10# $1 = image name 11# $2 = container name 12# $3 = architecture (x86_64 or aarch64) 13# $4 = user name 14# $5 = user ID 15# $6 = persistent? 16# $7 = path to sources dir 17# $8 = path to working dir 18# $9 = path to output dir 19# $10 = reuse image/container? (0: no reuse; 1: reuse image; 2: reuse container) 20# $11 = build image (when reuse = 0) 21# $12 = path to Dockerfile 22# $13 = path to docker context dir 23# $14 = docker_flags_len 24# $15 = (docker_flags) 25# $16 = _prepare_source_len 26# $17 = (_prepare_source) 27function build_with_docker() { 28 set -o errexit 29 set -x 30 31 local -a _docker_target=( ${1} ) 32 local _container_name=${2} 33 local _arch=${3} 34 local _docker_image=${1}_${_arch} 35 local _user=${4} 36 local _uid=${5} 37 local _persistent=${6} 38 39 if [[ ${_persistent} -eq 1 ]]; then 40 _docker_image=${1}_${_arch}_persistent 41 fi 42 local _docker_source= 43 if [ "${7}" != 'x' ]; then 44 _docker_source="-v ${7#x}:/source:rw" 45 fi 46 local _docker_working= 47 if [ "${8}" != 'x' ]; then 48 _docker_working="-v ${8#x}:/working:rw" 49 fi 50 local _docker_output= 51 if [ "${9}" != 'x' ]; then 52 _docker_output="-v ${9#x}:/output:rw" 53 fi 54 local _reuse=${10} 55 local _build_image=${11} 56 local _dockerfile=${12} 57 local _docker_context=${13} 58 shift 13 59 local -a _args=("$@") 60 local -i _docker_flags_len=${_args[0]} 61 local -a _docker_flags=("${_args[@]:1:$_docker_flags_len}") 62 local -i _prepare_source_len=${_args[(_docker_flags_len+1)]} 63 local -a _prepare_source=("${_args[@]:(_docker_flags_len+2):_prepare_source_len}") 64 65 local _build_or_retry=${_arch}_retry 66 67 if [[ ${_reuse} -ne 1 ]]; then 68 _build_or_retry=${_arch}_build 69 if [[ ${_persistent} -eq 1 ]]; then 70 _docker_target+=("${_docker_target[0]}_persistent") 71 fi 72 if [[ ${_build_image} -eq 1 ]]; then 73 if [[ ${_arch} != $(uname -m) ]]; then 74 export DOCKER_CLI_EXPERIMENTAL=enabled 75 # from 76 # https://community.arm.com/developer/tools-software/tools/b/tools-software-ides-blog/posts/getting-started-with-docker-for-arm-on-linux 77 docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3 78 docker buildx create \ 79 --name docker_vmm_${_arch}_builder \ 80 --platform ${map_uname_to_docker_builder_arch[${_arch}]} \ 81 --use 82 docker buildx inspect --bootstrap 83 for _target in ${_docker_target[@]}; do 84 docker buildx build \ 85 --platform ${map_uname_to_docker_builder_arch[${_arch}]} \ 86 --target ${_target} \ 87 -f ${_dockerfile} \ 88 -t ${_docker_image}:latest \ 89 ${_docker_context} \ 90 --build-arg USER=${_user} \ 91 --build-arg UID=${_uid} --load 92 done 93 docker buildx rm docker_vmm_${_arch}_builder 94 unset DOCKER_CLI_EXPERIMENTAL 95 else 96 for _target in ${_docker_target[@]}; do 97 docker build \ 98 -f ${_dockerfile} \ 99 --target ${_target} \ 100 -t ${_docker_image}:latest \ 101 ${_docker_context} \ 102 --build-arg USER=${_user} \ 103 --build-arg UID=${_uid} 104 done 105 fi 106 fi 107 if [[ ${_persistent} -eq 1 ]]; then 108 if [[ -n "$(container_exists ${_container_name})" ]]; then 109 docker rm -f ${_container_name} 110 fi 111 docker run -d \ 112 --privileged \ 113 --name ${_container_name} \ 114 -h ${_container_name} \ 115 ${_docker_source} \ 116 ${_docker_working} \ 117 ${_docker_output} \ 118 -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ 119 ${_docker_image}:latest 120 fi 121# else 122# # If we are reusing the docker image, then we cannot change the target 123# # architecture (though we can change the persistence) of the container. 124# echo TODO 125 fi 126 127 if [[ ${_persistent} -eq 1 ]]; then 128 if [[ "$(docker inspect --format='{{.State.Status}}' ${_container_name})" == "paused" ]]; then 129 docker unpause ${_container_name} 130 fi 131 docker exec -it \ 132 --user ${_user} \ 133 ${_docker_flags[@]} \ 134 ${_container_name} \ 135 /static/rebuild-internal.sh ${_prepare_source[@]} ${_build_or_retry} 136 docker pause ${_container_name} 137 else 138 docker run -it --rm \ 139 --user ${_user} \ 140 ${_docker_flags[@]} \ 141 ${_docker_source} \ 142 ${_docker_working} \ 143 ${_docker_output} \ 144 ${_docker_image}:latest \ 145 /static/rebuild-internal.sh ${_prepare_source[@]} ${_build_or_retry} 146 fi 147} 148 149build_with_docker $@ 150