Skip to content

Latest commit

 

History

History
169 lines (116 loc) · 6.53 KB

README.md

File metadata and controls

169 lines (116 loc) · 6.53 KB

eve-rust

Base image for building rust-based executables in containers for the EVE platform. Contains the basic rust binaries such as rustc, cargo, rustup, etc., as well as additional plugins and targets. As of this writing:

  • cargo-chef - a tool for building and caching dependencies for a rust project
  • cargo-sbom - a tool for generating SBoMs for rust-based projects
  • targets to build for linux amd64, arm64 and riscv64 on linux for both musl and glibc

The image also includes additional tools to support cross-compilation

  • mold - a very fast linker for cross-compilation targets
  • clang - to invoke mold for cross-compilation targets

Usage

Use this image as a base FROM when building in your EVE Dockerfile. For example:

FROM lfedge/eve-rust:1.80.1 AS rust

ADD https://github.com/foo/bar.git#v1.2.3 /src/foo
WORKDIR /src/foo

# tools already in place
RUN cargo build --release
RUN cargo sbom > sbom.spdx.json

FROM lfedge/eve-alpine:1f7685f95a475c6bbe682f0b976f12180b6c8726 AS build
# do the rest of your regular eve-alpine work

COPY --from=rust /src/foo/target/release/foo /out/foo

FROM scratch

COPY --from=build /out/ /

The above assumes that you do not need additional eve-alpine packages inside the rust build stage. This should work for the overwhelming majority of cases. If it does not work for you, and you need to use the rust toolchain inside of your build FROM eve-alpine,, you can copy the build toolchain from eve-rust into your eve-alpine image. For example:

FROM lfedge/eve-rust:1.80.1 AS rust
FROM lfedge/eve-alpine:1f7685f95a475c6bbe682f0b976f12180b6c8726 AS build

ENV BUILD_PKGS packages you need for build # e.g. gcc, make, etc.
ENV PKGS packages you need for final install # e.g. mtools dosfstools
RUN eve-alpine-deploy.sh

# copy over the tooling we need from the rust image
# ALL OF THESE STEPS ARE REQUIRED
COPY --from=rust /usr/local/cargo /usr/local/cargo
COPY --from=rust /usr/local/rustup /usr/local/rustup
ENV RUSTUP_HOME=/usr/local/rustup
ENV PATH=/usr/local/cargo/bin:${PATH}
ENV CARGO_HOME=/usr/local/cargo

# build as before
ADD https://github.com/foo/bar.git#v1.2.3 /src/foo
WORKDIR /src/foo
RUN cargo build --release
RUN cargo sbom > sbom.spdx.json

SBoM

All EVE packages must have an SBoM. When the packages are built using linuxkit pkg build, which itself calls buildkit, the SBoM is automatically generated and included in the package. It only scans the final stage of the image. In the case of rust-generated binaries, the final binary does not contain any information about dependencies, so the SBoM must be generated manually.

When building a package, you must:

  1. Generate the sbom using cargo sbom > sbom.spdx.json
  2. Copy the sbom.spdx.json into the final image

Hence, the following are mandatory stages:

# in the build stage FROM eve-rust, before or after `cargo build`
RUN cargo sbom > target/sbom.spdx.json

# in the final FROM scratch stage
COPY --from=rust /src/foo/target/sbom.spdx.json /sbom.spdx.json

The above will go away when the sbom generation is a built-in part of cargo, to be enabled by configuration. See this RFC.

Cross-compilation

To enable cross-compilation we need few extra steps. By default cargo builds for host platform so the target must be specified explicitly either using --target <target> or by setting CARGO_BUILD_TARGET environment variable. See Cargo docs

# we use host tools to avoid emulation and slow builds
FROM --platform=$BUILDPLATFORM lfedge/eve-rust:1.80.1 AS rust-host
ARG TARGETARCH

# map Docker's $TARGETARCH to Rust target
FROM rust-host AS target-amd64
ENV CARGO_BUILD_TARGET="x86_64-unknown-linux-musl"

FROM rust-host AS target-arm64
ENV CARGO_BUILD_TARGET="aarch64-unknown-linux-musl"

FROM rust-host AS target-riscv64
ENV CARGO_BUILD_TARGET="riscv64gc-unknown-linux-gnu"

FROM target-$TARGETARCH AS rust

ADD https://github.com/foo/bar.git#v1.2.3 /src/foo
WORKDIR /src/foo

# invoke you build here e.g. cargo build --release

# cargo creates a subdirectory /<your app>/target/$CARGO_BUILD_TARGET
# copy build artifacts to a common place to avoid passing extra ARG to following
# stage that doesn't inherit the environment
RUN cp /src/foo/target/$CARGO_BUILD_TARGET/release/foo /src/foo/target/release/foo


FROM lfedge/eve-alpine:1f7685f95a475c6bbe682f0b976f12180b6c8726 AS build
# do the rest of your regular eve-alpine work

COPY --from=rust /src/foo/target/release/foo /out/foo

FROM scratch

COPY --from=build /out/ /

Supported platforms

This image is built for linux/amd64 and linux/arm64. riscv64 is not supported yet as a host platform, and therefore no image is released for riscv64. When rust on alpine is fully ready, it will be added, likely with alpine 3.21.

Supported target platforms are listed in the Dockerfile. As of this writing, these are:

  • x86_64-unknown-linux-musl
  • aarch64-unknown-linux-musl
  • x86_64-unknown-linux-gnu
  • aarch64-unknown-linux-gnu
  • riscv64gc-unknown-linux-gnu

Note that riscv64 is supported gnu only, not musl, and so is not usable on Alpine-based systems without first installing glibc. This, too, will be fixed when rust on alpine is fully ready.

Versioning

The version of this image is the version of the rust toolchain it contains. This makes it easy to know what version of rust you are using. For rust version 1.80.1, the image tag is lfedge/eve-rust:1.80.1.

We try very hard never to cut a new image of eve-rust that uses the same rust version as a previous one. For example, if eve-rust:1.80.1 is released, and we need to add a new cargo plugin or build target, we will bump to a newer version of rust and include it, thus getting to eve-rust:1.80.2.

In the rare case that this does not work, and we must release a new image of eve-rust with the same rust version as an already-released image of eve-rust, we will append a patch version to the tag. For example, if eve-rust:1.80.1 is released, and we need to add a new cargo plugin or build target, we will release eve-rust:1.80.1-1, where -1 is the sequential eve-rust patch version. This will be very short-lived, only as long as we need to get to the next version of rust.

New versions are released to Docker Hub by adding a tag, e.g. 1.80.1 or 1.80.1-1. The GitHub Actions workflow checks that it matches the version in the Dockerfile, and if it does not, it will fail the build.