blob: 7d23c56d9a2707ccf6e35756776c289224bc9da8 [file] [log] [blame]
# Copyright 2020 The IREE Authors
#
# Licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set -euo pipefail
# It's convenient to have the paths inside the container match the paths
# outside. This creates an issue, however, because we pass around CMake build
# directories, which use absolute paths, so it's important that the paths match
# between runners. Doing things this way allows runners to change their working
# directory and enables local reproduction of issues.
DOCKER_CONTAINER_WORKDIR="${DOCKER_CONTAINER_WORKDIR:-/work}"
# Sets up files and environment to enable running scripts in docker.
# In particular, does some shenanigans to enable running with the current user.
# Some of this setup is only strictly necessary for Bazel, but it doesn't hurt
# for anything else.
# Requires that DOCKER_HOST_WORKDIR and DOCKER_HOST_TMPDIR have been set
function docker_run() {
# Make the source repository available and launch containers in that
# directory.
DOCKER_RUN_ARGS=(
--mount="type=bind,source=${DOCKER_HOST_WORKDIR},dst=${DOCKER_CONTAINER_WORKDIR}"
--workdir="${DOCKER_CONTAINER_WORKDIR}"
--env "CCACHE_BASE_DIR=${DOCKER_CONTAINER_WORKDIR}"
)
# Delete the container after the run is complete.
DOCKER_RUN_ARGS+=(--rm)
# Run as the current user and group. If only it were this simple...
DOCKER_RUN_ARGS+=(--user="$(id -u):$(id -g)")
# Use the host network stack. Improves network performance and makes it
# possible for the container to talk to localhost.
DOCKER_RUN_ARGS+=(--network="host")
# The Docker container doesn't know about the users and groups of the host
# system. We have to tell it. This is just a mapping of IDs to names though.
# The thing that really matters is the IDs, so the key thing is that Docker
# writes files as the same ID as the current user, which we set above, but
# without the group and passwd file, lots of things get upset because they
# don't recognize the current user ID (e.g. `whoami` fails). Bazel in
# particular looks for a home directory and is not happy when it can't find
# one.
# So we make the container share the host mapping, which guarantees that the
# current user is mapped. If there was any user or group in the container
# that we cared about, this wouldn't necessarily work because the host and
# container don't necessarily map the ID to the same user. Luckily though,
# we don't.
# We don't just mount the real /etc/passwd and /etc/group because Google
# Linux workstations do some interesting stuff with user/group permissions
# such that they don't contain the information about normal users and we
# want these scripts to be runnable locally for debugging.
# Instead we dump the results of `getent` to some fake files.
local fake_etc_dir="${DOCKER_HOST_TMPDIR}/fake_etc"
mkdir -p "${fake_etc_dir}"
local fake_group="${fake_etc_dir}/group"
local fake_passwd="${fake_etc_dir}/passwd"
getent group > "${fake_group}"
getent passwd > "${fake_passwd}"
DOCKER_RUN_ARGS+=(
--mount="type=bind,src=${fake_group},dst=/etc/group,readonly"
--mount="type=bind,src=${fake_passwd},dst=/etc/passwd,readonly"
)
# Bazel stores its cache in the user home directory by default. It's
# possible to override this, but that would require changing our Bazel
# startup options, which means polluting all our scripts and making them not
# runnable locally. Instead, we give it a special home directory to write
# into. We don't just mount the user home directory (or some subset thereof)
# for two reasons:
# 1. We probably don't want Docker to just write into the user's home
# directory when running locally.
# 2. This allows us to control the device the home directory is in. Bazel
# tends to be IO bound at even moderate levels of CPU parallelism and
# the difference between a persistent SSD and a local scratch SSD can
# be huge.
local fake_home_dir="${DOCKER_HOST_TMPDIR}/fake_home"
mkdir -p "${fake_home_dir}"
DOCKER_RUN_ARGS+=(
--mount="type=bind,src=${fake_home_dir},dst=${HOME}"
)
# Make gcloud credentials available if they are present. This isn't
# necessary when running in GCE but enables using this script locally with
# remote caching.
if [[ -d "${HOME}/.config/gcloud" ]]; then
DOCKER_RUN_ARGS+=(
--mount="type=bind,src=${HOME}/.config/gcloud,dst=${HOME}/.config/gcloud,readonly"
)
fi
# Give the container a ramdisk and set the Bazel sandbox base to point to
# it. This helps a lot with Bazel getting IO bound. Note that SANDBOX_BASE
# is a custom environment variable we translate into the corresponding Bazel
# option.
DOCKER_RUN_ARGS+=(
--mount="type=tmpfs,dst=/dev/shm"
--env SANDBOX_BASE=/dev/shm
)
# Some scripts need elevated permissions to control system-level scheduling.
# Since we're not using Docker for sandboxing, it is fine to run in
# privileged mode.
DOCKER_RUN_ARGS+=(
--privileged
)
docker run "${DOCKER_RUN_ARGS[@]}" "$@"
}
docker_run "$@"