# 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 "$@"