diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..d059baf21 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +### output directories +.tmp/ +output/ +cache/ diff --git a/.gitignore b/.gitignore index 51496aaad..b443fb1d8 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ ubuntu-*-cloudimg-console.log ### compile configurations added by users /config-*.conf +### but not default (supplied) files +!/config-docker.conf ### output directories /.tmp/ diff --git a/Dockerfile b/Dockerfile index 10da28b82..bcf5b6b21 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,17 @@ FROM ubuntu:16.04 -RUN apt-get update -RUN apt-get install -y git build-essential binutils -WORKDIR /root -RUN git clone https://github.com/igorpecovnik/lib/ -RUN cp lib/compile.sh . +RUN dpkg --add-architecture i386 +RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y git dialog lsb-release binutils wget ca-certificates device-tree-compiler \ + pv bc lzop zip binfmt-support build-essential ccache debootstrap ntpdate gawk gcc-arm-linux-gnueabihf gcc-arm-linux-gnueabi \ + qemu-user-static u-boot-tools uuid-dev zlib1g-dev unzip libusb-1.0-0-dev ntpdate parted pkg-config libncurses5-dev whiptail \ + debian-keyring debian-archive-keyring f2fs-tools libfile-fcntllock-perl rsync libssl-dev nfs-kernel-server btrfs-tools \ + gcc-aarch64-linux-gnu ncurses-term p7zip-full dos2unix dosfstools libc6-dev-armhf-cross libc6-dev-armel-cross libc6-dev-arm64-cross \ + curl gcc-arm-none-eabi libnewlib-arm-none-eabi patchutils python liblz4-tool libpython2.7-dev linux-base swig libpython-dev \ + systemd-container udev distcc libstdc++-arm-none-eabi-newlib gcc-4.9-arm-linux-gnueabihf gcc-4.9-aarch64-linux-gnu \ + g++-4.9-arm-linux-gnueabihf g++-4.9-aarch64-linux-gnu g++-5-aarch64-linux-gnu g++-5-arm-linux-gnueabihf lib32stdc++6 \ + libc6-i386 lib32ncurses5 lib32tinfo5 locales ncurses-base zlib1g:i386 aptly +RUN locale-gen en_US.UTF-8 +ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' LC_ALL='en_US.UTF-8' TERM=screen +WORKDIR /root/armbian +COPY . /root/armbian +ENTRYPOINT [ "/bin/bash", "/root/armbian/compile.sh" ] diff --git a/config-docker.conf b/config-docker.conf new file mode 100644 index 000000000..2f3342a0f --- /dev/null +++ b/config-docker.conf @@ -0,0 +1,69 @@ +# DO NOT EDIT THIS FILE +# +# This is a Docker launcher file. To set up the configuration, use command line arguments to compile.sh +# or create a config file named "config-docker-guest.conf" based on config-example.conf + +[[ ! -c /dev/loop-control ]] && display_alert "/dev/loop-control does not exist, image building may not work" "" "wrn" + +# remove "docker" from the command line since "docker-guest" will be passed instead +shift + +# build a new container based on provided Dockerfile +display_alert "Building a Docker container" +docker build -t armbian . + +DOCKER_FLAGS=() + +# Running this container in privileged mode is a simple way to solve loop device access issues +#DOCKER_FLAGS+=(--privileged) + +# add only required capabilities instead (though MKNOD should be already present) +DOCKER_FLAGS+=(--cap-add=SYS_ADMIN --cap-add=MKNOD) + +# mounting things inside the container on Ubuntu won't work without this +# https://github.com/moby/moby/issues/16429#issuecomment-217126586 +DOCKER_FLAGS+=(--security-opt=apparmor:unconfined) + +# remove resulting container after exit +DOCKER_FLAGS+=(--rm) + +# pass through loop devices +for d in /dev/loop*; do + DOCKER_FLAGS+=(--device=$d) +done + +# accessing dynamically created devices won't work by default +# and --device doesn't accept devices that don't exist at the time "docker run" is executed +# https://github.com/moby/moby/issues/27886 +# --device-cgroup-rule requires new Docker version + +# allow loop devices (not required) +DOCKER_FLAGS+=(--device-cgroup-rule='b 7:* rmw') +# allow loop device partitions +DOCKER_FLAGS+=(--device-cgroup-rule='b 259:* rmw') + +# this is an ugly hack, but it is required to get /dev/loopXpY minor number +# for mknod inside the container, and container itself still uses private /dev internally +DOCKER_FLAGS+=(-v /dev:/tmp/dev:ro) + +# mount 2 named volumes - for cacheable data and compiler cache +DOCKER_FLAGS+=(-v=armbian-cache:/root/armbian/cache -v=armbian-ccache:/root/.ccache) + +# mount 2 local directories - output and userpatches +DOCKER_FLAGS+=(-v=$SRC/output:/root/armbian/output -v=$SRC/userpatches:/root/armbian/userpatches) + +# pass other command line arguments like KERNEL_ONLY=yes, KERNEL_CONFIGURE=yes, etc. +# pass "docker-guest" as an additional config name that will be sourced in the container if exists +display_alert "Running the container" +docker run "${DOCKER_FLAGS[@]}" -it armbian docker-guest "$@" + +STATUS=$? + +if [[ $STATUS -ge 125 && $STATUS -le 127 ]]; then + display_alert "Docker error" "$STATUS" "wrn" + display_alert "please make sure you are using the latest version (17.06 CE or newer)" "" "wrn" + display_alert "please check the Armbian documentation for the Docker setup procedure" "" "wrn" +fi + +# don't need to proceed further on the host +exit 0 diff --git a/lib/debootstrap-ng.sh b/lib/debootstrap-ng.sh index 160ba8c94..06930bac3 100644 --- a/lib/debootstrap-ng.sh +++ b/lib/debootstrap-ng.sh @@ -365,10 +365,17 @@ prepare_partitions() LOOP=$(losetup -f) [[ -z $LOOP ]] && exit_with_error "Unable to find free loop device" - # NOTE: losetup -P option is not available in Trusty - [[ $CONTAINER_COMPAT == yes && ! -e $LOOP ]] && mknod -m0660 $LOOP b 7 ${LOOP//\/dev\/loop} > /dev/null + # check config-docker.conf for details on this hack + if [[ ! -b $LOOP ]]; then + if [[ $CONTAINER_COMPAT == yes && -b /tmp/$LOOP ]]; then + display_alert "Creating device node" "$LOOP" + mknod -m0660 $LOOP b 7 0x$(stat -c '%T' /tmp/$LOOP) + else + exit_with_error "Device node $LOOP does not exist" + fi + fi - # TODO: Needs mknod here in Docker? + # NOTE: losetup -P option is not available in Trusty losetup $LOOP ${SDCARD}.raw # loop device was grabbed here, unlock @@ -380,7 +387,14 @@ prepare_partitions() rm -f $SDCARD/etc/fstab if [[ -n $rootpart ]]; then display_alert "Creating rootfs" "$ROOTFS_TYPE" - [[ $CONTAINER_COMPAT == yes ]] && mknod -m0660 ${LOOP}p${rootpart} b 259 $rootpart > /dev/null + if [[ ! -b ${LOOP}p${rootpart} ]]; then + if [[ $CONTAINER_COMPAT == yes && -b /tmp/${LOOP}p${rootpart} ]]; then + display_alert "Creating device node" "${LOOP}p${rootpart}" + mknod -m0660 ${LOOP}p${rootpart} b 259 0x$(stat -c '%T' /tmp/${LOOP}p${rootpart}) + else + exit_with_error "Device node ${LOOP}p${rootpart} does not exist" + fi + fi mkfs.${mkfs[$ROOTFS_TYPE]} ${mkopts[$ROOTFS_TYPE]} ${LOOP}p${rootpart} [[ $ROOTFS_TYPE == ext4 ]] && tune2fs -o journal_data_writeback ${LOOP}p${rootpart} > /dev/null [[ $ROOTFS_TYPE == btrfs ]] && local fscreateopt="-o compress-force=zlib" @@ -390,7 +404,14 @@ prepare_partitions() fi if [[ -n $bootpart ]]; then display_alert "Creating /boot" "$bootfs" - [[ $CONTAINER_COMPAT == yes ]] && mknod -m0660 ${LOOP}p${bootpart} b 259 $bootpart > /dev/null + if [[ ! -b ${LOOP}p${bootpart} ]]; then + if [[ $CONTAINER_COMPAT == yes && -b /tmp/${LOOP}p${bootpart} ]]; then + display_alert "Creating device node" "${LOOP}p${bootpart}" + mknod -m0660 ${LOOP}p${bootpart} b 259 0x$(stat -c '%T' /tmp/${LOOP}p${bootpart}) + else + exit_with_error "Device node ${LOOP}p${bootpart} does not exist" + fi + fi mkfs.${mkfs[$bootfs]} ${mkopts[$bootfs]} ${LOOP}p${bootpart} mkdir -p $MOUNT/boot/ mount ${LOOP}p${bootpart} $MOUNT/boot/ diff --git a/lib/general.sh b/lib/general.sh index 8b0c8c6d4..45863dffa 100644 --- a/lib/general.sh +++ b/lib/general.sh @@ -477,6 +477,7 @@ prepare_host() fi # packages list for host + # NOTE: please sync any changes here with the Dockerfile local hostdeps="wget ca-certificates device-tree-compiler pv bc lzop zip binfmt-support build-essential ccache debootstrap ntpdate \ gawk gcc-arm-linux-gnueabihf gcc-arm-linux-gnueabi qemu-user-static u-boot-tools uuid-dev zlib1g-dev unzip libusb-1.0-0-dev ntpdate \ parted pkg-config libncurses5-dev whiptail debian-keyring debian-archive-keyring f2fs-tools libfile-fcntllock-perl rsync libssl-dev \ @@ -499,10 +500,16 @@ prepare_host() display_alert "Running in container" "$(systemd-detect-virt)" "info" # disable apt-cacher unless NO_APT_CACHER=no is not specified explicitly if [[ $NO_APT_CACHER != no ]]; then - display_alert "apt-cacher is disabled, set NO_APT_CACHER=no to override" "" "wrn" + display_alert "apt-cacher is disabled in containers, set NO_APT_CACHER=no to override" "" "wrn" NO_APT_CACHER=yes fi CONTAINER_COMPAT=yes + # trying to use nested containers is not a good idea, so don't permit EXTERNAL_NEW=compile + if [[ $EXTERNAL_NEW == compile ]]; then + display_alert "EXTERNAL_NEW=compile is not available when running in container, setting to prebuilt" "" "wrn" + EXTERNAL_NEW=prebuilt + fi + SYNC_CLOCK=no fi fi