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