From 63481da13d8ba67a4858e7e41951208e8e00bc79 Mon Sep 17 00:00:00 2001 From: Martijn Pieters Date: Thu, 30 Jan 2025 17:42:06 +0000 Subject: [PATCH] Use docker cache mounts for apt, pip and cargo The cache mounts are cached using standard github actions cache when building in the CI pipeline. Note that the build stage no longer contains the whole source tree, these are instead mounted into the build container when building to avoid invalidating cached build container layers. --- .github/workflows/build-docker.yml | 44 ++++++++++++++++++++++++++++++ Dockerfile | 32 ++++++++++++++++------ 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index 843d80e4b2df..5e02816a4718 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -39,6 +39,8 @@ jobs: # Login to DockerHub first, to avoid rate-limiting - uses: docker/login-action@v3 + # PRs from forks don't have access to secrets, disable this step in that case. + if: ${{ github.event.pull_request.head.repo.full_name == 'astral-sh/uv' }} with: username: astralshbot password: ${{ secrets.DOCKERHUB_TOKEN_RO }} @@ -79,6 +81,48 @@ jobs: platform=${{ matrix.platform }} echo "PLATFORM_TUPLE=${platform//\//-}" >> $GITHUB_ENV + - name: Docker apt & pip caches + uses: actions/cache@v4 + id: docker-caches + with: + path: | + var-cache-apt + var-lib-apt + root-cache-pip + key: docker-caches-${{ matrix.platform }}-${{ hashFiles('Dockerfile') }} + + - name: Docker Cargo caches + uses: actions/cache@v4 + id: docker-cargo-caches + with: + path: | + root-target + usr-local-cargo-git-db + usr-local-cargo-registry + key: docker-cargo-caches-${{ matrix.platform }}-${{ hashFiles('Dockerfile', 'crates/**', 'Cargo.toml', 'Cargo.lock') }} + + - name: Inject apt & pip caches into docker + uses: reproducible-containers/buildkit-cache-dance@v3 + with: + cache-map: | + { + "var-cache-apt": "/var/cache/apt", + "var-lib-apt": "/var/lib/apt", + "root-cache-pip": "/root/.cache/pip" + } + skip-extraction: ${{ steps.docker-caches.outputs.cache-hit }} + + - name: Inject Cargo caches into docker + uses: reproducible-containers/buildkit-cache-dance@v3 + with: + cache-map: | + { + "root-target": "/root/target", + "usr-local-cargo-git-db": "/usr/local/cargo/git/db", + "usr-local-cargo-registry": "/usr/local/cargo/registry/" + } + skip-extraction: ${{ steps.docker-cargo-caches.outputs.cache-hit }} + # Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/ - name: Build and push by digest id: build diff --git a/Dockerfile b/Dockerfile index 744909a181f6..fda1e2c7c442 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,18 +2,25 @@ FROM --platform=$BUILDPLATFORM ubuntu AS build ENV HOME="/root" WORKDIR $HOME -RUN apt update \ +RUN \ + --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + # remove the default docker-specific apt config that auto-deletes /var/apt/cache archives + rm -f /etc/apt/apt.conf.d/docker-clean && \ + # and configure apt-get to keep downloaded archives in the cache + echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache && \ + apt update \ && apt install -y --no-install-recommends \ build-essential \ curl \ python3-venv \ - cmake \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* + cmake # Setup zig as cross compiling linker RUN python3 -m venv $HOME/.venv -RUN .venv/bin/pip install cargo-zigbuild +RUN \ + --mount=type=cache,target=/root/.cache/pip \ + .venv/bin/pip install cargo-zigbuild ENV PATH="$HOME/.venv/bin:$PATH" # Install rust @@ -32,10 +39,17 @@ ENV PATH="$HOME/.cargo/bin:$PATH" RUN rustup target add $(cat rust_target.txt) # Build -COPY crates crates -COPY ./Cargo.toml Cargo.toml -COPY ./Cargo.lock Cargo.lock -RUN case "${TARGETPLATFORM}" in \ +RUN \ + # bind mounts to access Cargo config, lock, and sources, without having to + # copy them into the build layer and so bloat the docker build cache + --mount=type=bind,source=crates,target=crates \ + --mount=type=bind,source=Cargo.toml,target=Cargo.toml \ + --mount=type=bind,source=Cargo.lock,target=Cargo.lock \ + # Cache mounts to speed up builds + --mount=type=cache,target=/root/target/ \ + --mount=type=cache,target=/usr/local/cargo/git/db \ + --mount=type=cache,target=/usr/local/cargo/registry/ \ + case "${TARGETPLATFORM}" in \ "linux/arm64") export JEMALLOC_SYS_WITH_LG_PAGE=16;; \ esac && \ cargo zigbuild --bin uv --bin uvx --target $(cat rust_target.txt) --release