Skip to content

Commit 3c2dc0f

Browse files
committed
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.
1 parent d517b1c commit 3c2dc0f

File tree

2 files changed

+77
-16
lines changed

2 files changed

+77
-16
lines changed

.github/workflows/build-docker.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ jobs:
3939

4040
# Login to DockerHub first, to avoid rate-limiting
4141
- uses: docker/login-action@v3
42+
# PRs from forks don't have access to secrets, disable this step in that case.
43+
if: ${{ github.event.pull_request.head.repo.full_name == 'astral-sh/uv' }}
4244
with:
4345
username: astralshbot
4446
password: ${{ secrets.DOCKERHUB_TOKEN_RO }}
@@ -79,6 +81,44 @@ jobs:
7981
platform=${{ matrix.platform }}
8082
echo "PLATFORM_TUPLE=${platform//\//-}" >> $GITHUB_ENV
8183
84+
- name: Docker build caches
85+
uses: actions/cache@v4
86+
id: docker-build-caches
87+
with:
88+
path: |
89+
var-cache-apt
90+
var-lib-apt
91+
tool-caches
92+
key: docker-caches-${{ matrix.platform }}-${{ hashFiles('Dockerfile') }}
93+
94+
- name: Docker Cargo target cache
95+
uses: actions/cache@v4
96+
id: docker-cargo-target-cache
97+
with:
98+
path: |
99+
root-target
100+
key: docker-cargo-target-cache-${{ matrix.platform }}-${{ hashFiles('Dockerfile', 'crates/**', 'Cargo.toml', 'Cargo.lock') }}
101+
102+
- name: Inject build caches into docker
103+
uses: reproducible-containers/buildkit-cache-dance@v3
104+
with:
105+
cache-map: |
106+
{
107+
"var-cache-apt": "/var/cache/apt",
108+
"var-lib-apt": "/var/lib/apt",
109+
"tool-caches": {"target": "/buildkit-cache", "id": "tool-caches"}
110+
}
111+
skip-extraction: ${{ steps.docker-build-caches.outputs.cache-hit }}
112+
113+
- name: Inject Cargo caches into docker
114+
uses: reproducible-containers/buildkit-cache-dance@v3
115+
with:
116+
cache-map: |
117+
{
118+
"root-target": "/root/target"
119+
}
120+
skip-extraction: ${{ steps.docker-cargo-target-cache.outputs.cache-hit }}
121+
82122
# Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/
83123
- name: Build and push by digest
84124
id: build

Dockerfile

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,32 @@
11
FROM --platform=$BUILDPLATFORM ubuntu AS build
2-
ENV HOME="/root"
2+
ENV HOME="/root" \
3+
# Place tool-specific caches in the buildkit tool cache.
4+
CARGO_HOME=/buildkit-cache/cargo \
5+
CARGO_ZIGBUILD_CACHE_DIR=/buildkit-cache/cargo-zigbuild \
6+
PIP_CACHE_DIR=/buildkit-cache/pip \
7+
RUSTUP_HOME=/buildkit-cache/rustup \
8+
ZIG_GLOBAL_CACHE_DIR=/buildkit-cache/zig
39
WORKDIR $HOME
410

5-
RUN apt update \
11+
RUN \
12+
--mount=type=cache,target=/var/cache/apt,sharing=locked \
13+
--mount=type=cache,target=/var/lib/apt,sharing=locked \
14+
# remove the default docker-specific apt config that auto-deletes /var/apt/cache archives
15+
rm -f /etc/apt/apt.conf.d/docker-clean && \
16+
# and configure apt-get to keep downloaded archives in the cache
17+
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache && \
18+
apt update \
619
&& apt install -y --no-install-recommends \
720
build-essential \
821
curl \
922
python3-venv \
10-
cmake \
11-
&& apt clean \
12-
&& rm -rf /var/lib/apt/lists/*
23+
cmake
1324

1425
# Setup zig as cross compiling linker
1526
RUN python3 -m venv $HOME/.venv
16-
RUN .venv/bin/pip install cargo-zigbuild
27+
RUN \
28+
--mount=type=cache,target=/buildkit-cache,id="tool-caches" \
29+
.venv/bin/pip install cargo-zigbuild
1730
ENV PATH="$HOME/.venv/bin:$PATH"
1831

1932
# Install rust
@@ -25,21 +38,29 @@ RUN case "$TARGETPLATFORM" in \
2538
esac
2639

2740
# Update rustup whenever we bump the rust version
41+
ENV PATH="$CARGO_HOME/bin:$PATH"
2842
COPY rust-toolchain.toml rust-toolchain.toml
29-
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --target $(cat rust_target.txt) --profile minimal --default-toolchain none
30-
ENV PATH="$HOME/.cargo/bin:$PATH"
31-
# Installs the correct toolchain version from rust-toolchain.toml and then the musl target
32-
RUN rustup target add $(cat rust_target.txt)
43+
RUN \
44+
--mount=type=cache,target=/buildkit-cache,id="tool-caches" \
45+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --target $(cat rust_target.txt) --profile minimal --default-toolchain none \
46+
# Installs the correct toolchain version from rust-toolchain.toml and then the musl target
47+
&& rustup target add $(cat rust_target.txt)
3348

3449
# Build
35-
COPY crates crates
36-
COPY ./Cargo.toml Cargo.toml
37-
COPY ./Cargo.lock Cargo.lock
38-
RUN case "${TARGETPLATFORM}" in \
50+
RUN \
51+
# bind mounts to access Cargo config, lock, and sources, without having to
52+
# copy them into the build layer and so bloat the docker build cache
53+
--mount=type=bind,source=crates,target=crates \
54+
--mount=type=bind,source=Cargo.toml,target=Cargo.toml \
55+
--mount=type=bind,source=Cargo.lock,target=Cargo.lock \
56+
# Cache mounts to speed up builds
57+
--mount=type=cache,target=$HOME/target/ \
58+
--mount=type=cache,target=/buildkit-cache,id="tool-caches" \
59+
case "${TARGETPLATFORM}" in \
3960
"linux/arm64") export JEMALLOC_SYS_WITH_LG_PAGE=16;; \
4061
esac && \
41-
cargo zigbuild --bin uv --bin uvx --target $(cat rust_target.txt) --release
42-
RUN cp target/$(cat rust_target.txt)/release/uv /uv \
62+
cargo zigbuild --bin uv --bin uvx --target $(cat rust_target.txt) --release \
63+
&& cp target/$(cat rust_target.txt)/release/uv /uv \
4364
&& cp target/$(cat rust_target.txt)/release/uvx /uvx
4465
# TODO(konsti): Optimize binary size, with a version that also works when cross compiling
4566
# RUN strip --strip-all /uv

0 commit comments

Comments
 (0)