Rust, Docker, and the GHA layer caching problem
Lately I’ve been working on my own vibe-designed todo app rewrite in Rust1. Along the way I started looking for a sensible path to optimizing Docker image builds on GitHub Actions.
One of the solutions you can easily stumble upon is cargo-chef — it separates dependency fetching from building the actual code to better cache layers. The problem is it’s designed for simpler applications with a single lib.rs. In a workspace with more crates it doesn’t cache what it should, and every push ends up recompiling everything from scratch.
Two approaches I tried: buildkit cache dance2 — speeds things up a bit, but doesn’t cache brilliantly and adds its own time overhead3 — and swatinem/rust-cache, which works nicely on GHA for binary caching, but deploying Kartoteka as a Docker image on Coolify rules that action out.
Research turned up sccache as worth trying — I made an attempt, but Hetzner S3 is a no-go4. So Cloudflare R2 on the free tier as a potential alternative5.
For now I’m parking at cache dance. Not ruling out going toward my own runner with local cache — just on a slightly bigger server.
Footnotes
-
Kartoteka — somewhere between Todoist, Jira, Amazing Marvin, and Toggl. Classic scope creep. ↩
-
In Kartoteka’s case there’s also the exotic stack — Leptos — which means deploying the server binary together with the built frontend/wasm. ↩
-
Hetzner S3 bills storage in 1 TB blocks. A bit astronomical for one innocent backup and build artifacts. ↩
-
Yes, I know — suggesting I go back to Cloudflare when I’ve spent two weeks rewriting an MCP from a Cloudflare Worker to axum/rmcp specifically to get off the Cloudflare ecosystem, sure. ↩