Skip to content

Instantly share code, notes, and snippets.

@satmandu
Last active August 5, 2021 18:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save satmandu/6829f229d18363ddeaf52d4b43a80623 to your computer and use it in GitHub Desktop.
Save satmandu/6829f229d18363ddeaf52d4b43a80623 to your computer and use it in GitHub Desktop.
Updated ChromeOS docker container script
#!/bin/bash
# chromeos_docker.sh
# Usage:
# chromeos_docker.sh recoveryfileurl name milestone arch
# or if image.bin already exists this works too:
# chromeos_docker.sh dummy name milestone arch
# (Default is not to delete the image after download.)
# e.g.
# Example for x86_64:
# chromeos_docker.sh https://dl.google.com/dl/edgedl/chromeos/recovery/chromeos_13816.82.0_nocturne_recovery_stable-channel_mp.bin.zip nocturne 90 x86_64
# Example for armv7l:
# chromeos_docker.sh https://dl.google.com/dl/edgedl/chromeos/recovery/chromeos_13904.55.0_veyron-fievel_recovery_stable-channel_fievel-mp.bin.zip fievel 91 armv7l
# Examples for i686:
# chromeos_docker.sh https://dl.google.com/dl/edgedl/chromeos/recovery/chromeos_9334.72.0_x86-alex-he_recovery_stable-channel_alex-mp-v4.bin.zip alex 58 i686
# chromeos_docker.sh https://dl.google.com/dl/edgedl/chromeos/recovery/chromeos_9334.72.0_x86-zgb-he_recovery_stable-channel_zgb-mp-v3.bin.zip zgb 58 i686
# Recovery file update links are here: https://cros-updates-serving.appspot.com/
# Note that you may need further steps if you are on an x86_64 machine.
# See https://www.stereolabs.com/docs/docker/building-arm-container-on-x86/
#
# Note also you should have a registry setup.
# Instructions here: https://docs.docker.com/registry/deploying/
# If you setup your registry with an ssl cert, you may have fewer problems.
# You can set the registry URL with the REPOSITORY env variable.
# e.g. export REPOSITORY="dockerserver:5000"
imageurl="${1}"
name="${2}"
milestone="${3}"
ARCH="${4}"
: "${outdir:=$(pwd)}"
: "${REPOSITORY:=127.0.0.1:5000}"
: "${PKG_CACHE:=$outdir/pkg_cache}"
echo " image url:${imageurl}"
echo " name: ${name}"
echo " milestone: ${milestone}"
echo " ARCH: ${ARCH}"
echo " REPOSITORY: ${REPOSITORY}"
echo "output root: ${outdir}"
echo " PKG_CACHE: ${PKG_CACHE}"
userid=$(id -un)
tmpdir=$(mktemp -d docker_XXXX -p "$(pwd)")
function abspath {
echo $(cd "$1" && pwd)
}
countdown()
(
IFS=:
set -- $*
secs=$(( ${1#0} * 3600 + ${2#0} * 60 + ${3#0} ))
while [ $secs -gt 0 ]
do
sleep 1 &
printf "\r%02d:%02d:%02d" $((secs/3600)) $(( (secs/60)%60)) $((secs%60))
secs=$(( $secs - 1 ))
wait
done
echo
)
get_arch () {
if [[ ! -f "$ARCH/image.bin.${milestone}" ]] ; then
curl --retry 3 -Lf "$imageurl" -o "$ARCH"/image.bin.zip || ( echo "Download failed" && kill $$ )
unzip -p "$ARCH"/image.bin.zip > "$ARCH"/image.bin."${milestone}" && rm "$ARCH"/image.bin.zip
fi
sudo kpartx -d "$ARCH"/image.bin."${milestone}"
rootpart=$(sudo kpartx -v -a "$ARCH"/image.bin."${milestone}" | grep 'p3\b' | awk '{print $3}')
if [[ -n $rootpart ]]; then
sudo umount /dev/mapper/"$rootpart" || true
sudo mount -o ro -t ext4 /dev/mapper/"$rootpart" "$tmpdir"
else
rootpart=$(losetup | grep image.bin."${milestone}" | awk '{print $1}')
[[ -n $rootpart ]] && sudo mount -o ro -t ext4 "$rootpart" "$tmpdir"
fi
[[ -z "$rootpart" ]] && (echo "The downloaded recovery in image.bin.${milestone} doesn't look right." && kill $$)
chromeos_arch=$(file "$tmpdir"/bin/bash | awk '{print $7}' | sed 's/,//g')
echo "chromeos_arch is $chromeos_arch"
if [[ "$chromeos_arch" == "x86-64" ]]; then
ARCH_LIB=lib64
ARCH=x86_64
CREW_LIB_PREFIX=$CREW_PREFIX/$ARCH_LIB
CREW_PREFIX=/usr/local
DOCKER_PLATFORM=amd64
MARCH=x86-64
PLATFORM="linux/amd64"
SETARCH_ARCH=x86_64
elif [[ "$chromeos_arch" == "ARM" ]]; then
ARCH=armv7l
ARCH_LIB=lib
CREW_LIB_PREFIX=$CREW_PREFIX/$ARCH_LIB
CREW_PREFIX=/usr/local
DOCKER_PLATFORM=armv7
MARCH=armv7-a
PLATFORM="linux/arm/v7"
SETARCH_ARCH=armv7l
elif [[ "$chromeos_arch" == "Intel" ]]; then
ARCH=i686
ARCH_LIB=lib
CREW_LIB_PREFIX=$CREW_PREFIX/$ARCH_LIB
CREW_PREFIX=/usr/local
DOCKER_PLATFORM=amd64
MARCH=i686
PLATFORM="linux/amd64"
SETARCH_ARCH=i686
elif [[ "$chromeos_arch" == "file" ]]; then
echo "Error in determining image architecture."
exit 1
fi
}
import_to_Docker () {
if ! docker image ls | grep "${userid}"/crewbase-"${name}"-${ARCH}.m"${milestone}" ; then
cd "$tmpdir" && sudo tar -c . | docker import --platform ${PLATFORM} - "${userid}"/crewbase-"${name}"-${ARCH}.m"${milestone}"
fi
cd ..
sudo umount "$tmpdir"
rmdir "$tmpdir"
#rm image.bin."${milestone}"
}
build_dockerfile () {
cd "${outdir}" || exit
cat <<EOF > ./${ARCH}/Dockerfile
ARG UID=1000
FROM ${REPOSITORY}/crewbase-${name}-${ARCH}.m${milestone}:${DOCKER_PLATFORM}
#ENV LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:$CREW_LIB_PREFIX
# Set githup repo information being synced from for install.
ENV REPO=chromebrew
ENV OWNER=skycocker
ENV BRANCH=master
ENV ARCH=$ARCH
ENV PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/bin
ENV HOME=/home/chronos/user/
ENV LANG=en_US.UTF-8
ENV LC_all=en_US.UTF-8
ENV XML_CATALOG_FILES=/usr/local/etc/xml/catalog
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN passwd -d chronos && \
echo "chronos ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
echo -e 'set -a\nCREW_TESTING_REPO=https://github.com/satmandu/chromebrew.git\nCREW_TESTING_BRANCH=master\nCREW_TESTING=0\nset +a' >> /home/chronos/user/.profile && chown chronos:chronos /home/chronos/user/.profile && \
echo -e '[[ -e /usr/local/etc/profile ]] && source /usr/local/etc/profile\nset -a\nCFLAGS="-march=$MARCH"\n: "\${LANG:=en_US.UTF-8}"\n: "\${LC_ALL:=en_US.UTF-8}"\n[[ -d "/output/pkg_cache" ]] && CREW_CACHE_DIR=/output/pkg_cache\n[[ -n "\$CREW_CACHE_DIR" ]] && CREW_CACHE_ENABLED=1\nset +a\n' >> /home/chronos/user/.bashrc && \
chown chronos:chronos /home/chronos/user/.bashrc
# For testing a local install.sh script
# RUN --mount=type=bind,target=/input cp /input/install.sh.test /home/chronos/user/install.sh
RUN curl -Ls https://github.com/\$OWNER/\$REPO/raw/\$BRANCH/install.sh -o /home/chronos/user/install.sh && \
chown chronos /home/chronos/user/install.sh && \
chmod +x /home/chronos/user/install.sh
SHELL ["/usr/bin/sudo", "-E", "-n", "BASH_ENV=/home/chronos/user/.bashrc", "-u", "chronos", "/bin/bash", "-c"]
RUN --mount=type=bind,target=/input PATH=/usr/local/bin:/usr/local/sbin:\$PATH \
CREW_CACHE_DIR=/input/pkg_cache \
CREW_CACHE_ENABLED=1 \
OWNER=\$OWNER \
BRANCH=\$BRANCH \
/bin/bash /home/chronos/user/install.sh || true
RUN --mount=type=bind,target=/input yes | \
PATH=/usr/local/bin:/usr/local/sbin:\$PATH \
CREW_CACHE_DIR=/input/pkg_cache \
CREW_CACHE_ENABLED=1 \
crew install util_linux bash coreutils gcc11 || true
# We can use setarch now that util_linux is installed.
SHELL ["/usr/bin/sudo", "-E", "-n", "BASH_ENV=/home/chronos/user/.bashrc", "-u", "chronos", "setarch", "$SETARCH_ARCH", "/bin/bash", "-o", "pipefail", "-c"]
RUN --mount=type=bind,target=/input yes | \
PATH=/usr/local/bin:/usr/local/sbin:\$PATH \
CREW_CACHE_DIR=/input/pkg_cache \
CREW_CACHE_ENABLED=1 \
crew install psmisc buildessential || true
RUN gem update --silent -N --system && \
gem install -N rubocop
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN echo -e "cd /usr/local/lib/crew/packages\ncrew update" >> /home/chronos/user/.bashrc
EOF
}
build_docker_image_with_local_registry () {
docker ps
echo "Tag & Push starting in ..." && countdown "00:00:01"
if ! docker pull ${REPOSITORY}/crewbase-"${name}"-${ARCH}.m"${milestone}" ; then
docker tag "${userid}"/crewbase-"${name}"-${ARCH}.m"${milestone}" ${REPOSITORY}/crewbase-"${name}"-${ARCH}.m"${milestone}":${DOCKER_PLATFORM}
docker push ${REPOSITORY}/crewbase-"${name}"-${ARCH}.m"${milestone}":${DOCKER_PLATFORM}
fi
}
make_cache_links () {
mkdir -p ./${ARCH}/pkg_cache
for i in $(cd pkg_cache && ls ./*${ARCH}*.*xz)
do
ln -f pkg_cache/"$i" ./${ARCH}/pkg_cache/"$i" 2>/dev/null || ( [[ ! -f ./${ARCH}/pkg_cache/$i ]] && cp pkg_cache/"$i" ./${ARCH}/pkg_cache/"$i" )
done
}
build_docker_image () {
docker image ls
dangling_images=$(docker images --filter "dangling=true" -q --no-trunc)
[[ -n "$dangling_images" ]] && docker rmi -f $(docker images --filter "dangling=true" -q --no-trunc)
cp install.sh ./${ARCH}/
buildx_cmd="env PROGRESS_NO_TRUNC=1 DOCKER_BUILDKIT=1 docker build --progress=plain --squash --no-cache --tag ${REPOSITORY}/crewbase-${name}.m${milestone}:${DOCKER_PLATFORM} ./${ARCH}/"
echo "$buildx_cmd"
$buildx_cmd || echo "Docker Build Error."
}
make_docker_image_script () {
dockercmd="docker run --rm -v ${PKG_CACHE}:/usr/local/tmp/packages -v \$(pwd):/output -h \$(hostname)-${ARCH} -it ${REPOSITORY}/crewbase-${name}.m${milestone}:${DOCKER_PLATFORM} /usr/local/bin/setarch ${SETARCH_ARCH} sudo -i -u chronos /usr/local/bin/bash -i"
[[ -f $(abspath "${outdir}")/crewbase-${name}-${ARCH}.m${milestone}.sh ]] && rm $(abspath "${outdir}")/crewbase-"${name}"-${ARCH}.m"${milestone}".sh
echo -e "#!/bin/bash\n$dockercmd" > $(abspath "${outdir}")/crewbase-"${name}"-${ARCH}.m"${milestone}".sh && chmod +x $(abspath "${outdir}")/crewbase-"${name}"-${ARCH}.m"${milestone}".sh
}
enter_docker_image () {
echo "Running \"$dockercmd\" from \"$(abspath "${outdir}")/crewbase-${name}-${ARCH}.m${milestone}.sh\""
echo "Entering in..." && countdown "00:00:30"
exec "$(abspath "${outdir}")/crewbase-${name}-${ARCH}.m${milestone}.sh"
}
main () {
get_arch
mkdir "${outdir}"/{autobuild,built,packages,preinstall,postinstall,src_cache,tmp,${ARCH}} &> /dev/null
import_to_Docker
# This enables ipv6 for docker container
if ! docker container ls | grep ipv6nat ; then
docker run -d --name ipv6nat --privileged --network host --restart unless-stopped -v /var/run/docker.sock:/var/run/docker.sock:ro -v /lib/modules:/lib/modules:ro robbertkl/ipv6nat
fi
build_dockerfile
build_docker_image_with_local_registry
make_cache_links
build_docker_image
make_docker_image_script
[[ -z "$JUST_BUILD" ]] && enter_docker_image
}
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment