Awesome
bazel-rust-docker-example
This project is intended to demonstrate a Bazel setup for Rust services with Docker support.
It has the following features:
- 🏗 Bazel build system
- 🦀 Compile, test and run Rust binaries, libraries and tests
- 🧰 Cargo workspace and Cargo Raze for managing Rust dependencies
- 🧐 Support for Rust-analyzer (and VS Code)
- ⚖️ Optimized Rust compiler flags for release targets
- 📦 Minimal Docker Rust images with distroless/static-debian11 as base image (2.36MB)
- 🚀 CircleCI pipeline with Bazel remote-cache on AWS S3
- ⚙️ Support for cross-compiling Rust targets from MacOS to Linux using Musl
Prerequisites
-
Install Bazelisk
-
Install Rustup
-
Install Cargo Raze
$ cargo install cargo-raze
- For cross-compilation from MacOS to Linux musl targets, install musl-cross
$ brew install filosottile/musl-cross/musl-cross
- For Bazel remote cache, install https://github.com/buchgr/bazel-remote
Bazel Commands
Build the entire project:
$ bazel build //...
Run all tests:
$ bazel test //...
Run service1 natively:
$ bazel run //service1:app
Run service1 within a Docker container:
$ bazel run //service1:image
⚠️ This only works when your host machine is Linux. Look for cross-compiling below when building on MacOS.
Run service1 within an optimzed release Docker container:
$ bazel run //service1:image --//:release
⚠️ This only works when your host machine is Linux. Look for cross-compiling below when building on MacOS.
Cross-compile service1 from MacOS to Linux and run within a Docker container:
$ bazel run //service1:image --platforms //build/platform:musl
Can also be combined with --//:release
.
Rust-Analyzer
In order for Rust-Analyzer to work, it is necessary to generate a rust-project.json
file. To do so, run
$ bazel run @rules_rust//tools/rust_analyzer:gen_rust_project
VS Code
When using VS Code as IDE, install the following extension for Rust-Analyzer: https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer
In your VS Code settings.json
, make sure to have the following configuration:
{
"rust-analyzer.checkOnSave.overrideCommand": ["cargo", "check" "--message-format=json"]
}
The Rust-Analyzer extension will pick up the rust-project.json
file which was generated earlier.
⚠️ Make sure to generate an updated rust-project.json
file whenever a new folder or dependency is added. It may also be needed to reload the workspace when the updated structure is not immediately recognized by Rust-Analyzer.
Cargo Dependencies
For each of the dependencies listed in any of the Cargo.toml
files, a Bazel build should be generated. This is done automatically by running
$ cargo raze
If not already the case, this will add a cargo
folder in the root of the project. Crates can now be referenced fron within Bazel through //cargo/*NAME*
(eg. //cargo/ferris_says
).
Adding a new dependency
After adding a new external dependency in any of the Cargo.toml
files, run the following steps:
- Run
cargo raze --generate-lockfile
- Run
bazel build //...
- Update
rust-project.json
by runningbazel run @rules_rust//tools/rust_analyzer:gen_rust_project
- Reload Rust Workspace in VS Code
- Start using crate in your Rust library or binary
Cross-compiling
This project provides a basic setup for cross-compiling from MacOS to Linux. The setup is inspired by rust-bazel-cross.
⚠️ A known limitation is that dependencies relying on macros fail to compile. More info here.
Bazel remote-cache
When applying the Bazel config flag --config=remote_cache
, Bazel will connect to a remote cache running at localhost:9090
. This server will sync files between a local cache and an AWS S3 bucket.
To start the bazel-remote server, run the script ./scripts/start_bazel_remote.sh
. Provide the following environment variables:
- AWS_REGION
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- AWS_S3_BUCKET_BAZEL_CACHE