| .woodpecker | ||
| .hadolint.yaml | ||
| Dockerfile | ||
| LICENSE.md | ||
| README.md | ||
| renovate.json | ||
rust-build-env
This is a ready-to-use Docker image for building and cross‑compiling Rust projects. It ships with Rust (via rustup), common cross targets, Zig, cargo‑zigbuild, cargo‑audit, cargo‑edit, cocogitto (cog), sccache, yq, lipo, specdown, nfpm, and cosign. It’s designed to feel at home in Woodpecker CI, but it works just as well on your laptop with docker run.
You can pull it from codeberg.org/purplebooth/rust-build-env. Most folks use the main tag for the latest build, or a specific version tag like vX.Y.Z when they want something pinned.
docker pull codeberg.org/purplebooth/rust-build-env:main
What's inside (in plain English)
You get the standard Rust toolchain managed by rustup and a bunch of targets preinstalled so you can cross‑compile right away: macOS (x86_64-apple-darwin, aarch64-apple-darwin), Windows (aarch64-pc-windows-gnullvm, x86_64-pc-windows-gnu), and Linux (both glibc and musl for x86_64 and aarch64). Rustfmt and Clippy are there too.
Zig 0.15.1 is included so cargo-zigbuild works out of the box. The image also includes cargo-zigbuild 0.20.1, cargo-audit 0.21.2, cargo-binstall 1.14.1, cargo-edit 0.13.7 (so cargo add, rm, set-version, and upgrade are available), cog 6.4.0 (from cocogitto), sccache 0.12.0, yq 4.48.1, lipo 0.10.0, and specdown 1.2.112. You’ll also find nfpm for packaging and cosign 3.0.2 for signing and verification. The base is Ubuntu with the usual build tools and OpenSSL headers, and there’s a non‑root user (nonroot) already set up with sudo if you want it.
The container’s working directory is /app. Rust lives under /usr/local/rustup and /usr/local/cargo, and the tools are on PATH.
Quick starts
If you just want to compile your project, mount it at /app and run Cargo like you normally would.
docker run --rm -it \
-v "$PWD":/app \
-w /app \
codeberg.org/purplebooth/rust-build-env:main \
cargo build
Cross‑compiling to a static Linux binary is straightforward with cargo-zigbuild.
docker run --rm -it \
-v "$PWD":/app \
-w /app \
codeberg.org/purplebooth/rust-build-env:main \
cargo zigbuild --release --target x86_64-unknown-linux-musl
If you need a universal macOS binary, build both architectures and glue them together with lipo.
docker run --rm -it \
-v "$PWD":/app \
-w /app \
codeberg.org/purplebooth/rust-build-env:main \
bash -lc '
cargo zigbuild --release --target aarch64-apple-darwin && \
cargo zigbuild --release --target x86_64-apple-darwin && \
lipo -create target/aarch64-apple-darwin/release/<binary> \
target/x86_64-apple-darwin/release/<binary> \
-o target/<binary>-universal'
Windows builds work the same way; just point at a Windows target.
docker run --rm -it \
-v "$PWD":/app \
-w /app \
codeberg.org/purplebooth/rust-build-env:main \
cargo zigbuild --release --target x86_64-pc-windows-gnu
If you want to speed things up, enable sccache by setting two environment variables when you run the container. The cache directory already exists in the image at /var/cache/sccache.
docker run --rm -it \
-e RUSTC_WRAPPER=/usr/local/bin/sccache \
-e SCCACHE_DIR=/var/cache/sccache \
-v "$PWD":/app \
-w /app \
codeberg.org/purplebooth/rust-build-env:main \
cargo build
Using it in Woodpecker CI
You don’t need anything fancy to use this image in Woodpecker. Point a step at the image and run Cargo. If you want builds to be snappy across pipelines, mount a couple of host volumes for the Cargo and sccache directories.
Here’s a simple pipeline that runs on pushes and pull requests and builds and tests your Rust project. It turns on sccache and caches both Cargo and sccache between runs using host volumes on the Woodpecker agent.
when:
- event: push
- event: pull_request
steps:
- name: build-and-test
image: codeberg.org/purplebooth/rust-build-env:main
environment:
RUSTC_WRAPPER: /usr/local/bin/sccache
SCCACHE_DIR: /var/cache/sccache
volumes:
- name: cargo-cache
path: /usr/local/cargo
- name: sccache-cache
path: /var/cache/sccache
commands:
- cargo fetch
- cargo build --locked
- cargo test --all --locked
volumes:
- name: cargo-cache
host:
path: /var/lib/woodpecker/cargo
- name: sccache-cache
host:
path: /var/lib/woodpecker/sccache
If you’re producing a cross‑compiled release, you can add another step that targets musl and saves the binary somewhere your pipeline expects. This example writes to a dist/ folder, which many release plugins look for.
- name: build-musl-release
image: codeberg.org/purplebooth/rust-build-env:main
environment:
RUSTC_WRAPPER: /usr/local/bin/sccache
SCCACHE_DIR: /var/cache/sccache
volumes:
- name: cargo-cache
path: /usr/local/cargo
- name: sccache-cache
path: /var/cache/sccache
commands:
- mkdir -p dist
- cargo zigbuild --release --target x86_64-unknown-linux-musl
- cp target/x86_64-unknown-linux-musl/release/<binary> dist/
And if you want a quick security check as part of CI, add a cargo-audit step. It takes seconds and will fail the build if known vulnerabilities are present in your dependency tree.
- name: audit
image: codeberg.org/purplebooth/rust-build-env:main
commands:
- cargo generate-lockfile || true
- cargo audit
Those examples are intentionally minimal. Feel free to sprinkle in formatting, packaging with nfpm, or signing artifacts with cosign 3.0.2 if your workflow needs it.
Notes on users and paths
The image creates a nonroot user with passwordless sudo, but it doesn’t force you to use it. By default, containers run as root in CI unless you set user: nonroot (or --user) yourself. Either way, the Rust and Cargo directories under /usr/local are writable and already on the PATH.
License
This project is released under The Unlicense. See LICENSE.