Skip to content

Image size: clean uv/go/cargo/apt caches out of image layers (BuildKit cache mounts) #10

Description

@ai-anant

Problem

The Dockerfile leaves build/download caches inside the image layers, permanently inflating every project image:

  1. uv cache: uv tool install semgrep + uv python install 3.13 download wheels into /root/.cache/uv (root stage) — semgrep alone is a 710 MB layer; a chunk of that is uv's download cache which is never cleaned.
  2. apt lists: cleaned in the main apt layer (rm -rf /var/lib/apt/lists/*) but the toolchain block runs sudo apt-get update and cleans only at the very end of the loop (sudo apt-get clean && sudo rm -rf /var/lib/apt/lists/*) — if the if is entered, ok; but caches from go install/cargo install are never removed.
  3. Go build cache: go install ...gosec@latest leaves $HOME/.cache/go-build + module cache in the image (~200–500 MB).
  4. Cargo: cargo install cargo-audit --locked compiles from source; ~/.cargo/registry + build artifacts can add 1+ GB to the image.
  5. npm: nodejs is installed via apt; npm itself isn't used at build time, but if a project-setup.sh runs npm, the cache persists (minor).

Proposal

Add a cache-cleanup layer right before the final WORKDIR, and use build-time-only caches where possible:

# Remove build-time caches so they never land in the image.
RUN rm -rf /root/.cache/uv /home/vscode/.cache/uv \
    && rm -rf /home/vscode/.cargo/registry /home/vscode/.cargo/target /home/vscode/.cache/go-build \
    && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb \
    && rm -rf /tmp/*

Better: use BuildKit cache mounts so caches never enter the layer at all:

RUN --mount=type=cache,target=/root/.cache/uv uv tool install semgrep
RUN --mount=type=cache,target=/var/cache/apt apt-get update && apt-get install -y ...

(--mount=type=cache keeps downloads in the builder cache — which already exists at 45 GB on this host — and out of the image.)

Expected saving: 500 MB – 1.5 GB per image depending on toolchains.

Files

  • templates/devcontainer/Dockerfile.tmpl — uv/apt/go/cargo steps

Acceptance criteria

  • docker history <image> shows no >100 MB layer from uv/cargo/go caches.
  • docker run --rm <image> du -sh /root/.cache /home/vscode/.cargo /home/vscode/.cache → all near-zero.
  • uv tool run semgrep --version still works after cleanup (semgrep is installed into UV_TOOL_DIR=/opt/uv/tools, not the cache).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions