kube-rs / kube

Rust Kubernetes client and controller runtime
https://kube.rs
Apache License 2.0
3k stars 307 forks source link

Document recommended deployment environment #332

Open nightkr opened 4 years ago

nightkr commented 4 years ago

331 highlights that this can be pretty confusing at the moment...

Arguably this isn't really specific to kube-rs, but at the same time it's probably something that will be relevant for 99% of kube-rs users.

nightkr commented 4 years ago

Personally, I'd lean towards crate2nix and buildLayeredImage because:

  1. It has much better caching behaviour than Dockerfiles (since it caches each Rust package individually, just like Cargo)
  2. It automatically figures out which dependencies are required at runtime, and tree-shakes the rest
  3. It can theoretically cross-build packages, but I'm not sure about whether the Rust tooling is set up for this yet

However, it does have some disadvantages...

  1. Nix doesn't have the mindshare of Dockerfiles
  2. It can take advantage of remote builders, but it's a bit messier to set up than Docker for Desktop
MikailBag commented 4 years ago

cargo-wharf is good at caching too.

nightkr commented 4 years ago

Oh, that's interesting. The caching seems stronger than for the plain Dockerfile setup, but there doesn't seem to be much of a story for non-cargo build steps (seeing apt invoked in the instructions is a bit worrying..). I'd also be a bit wary about encouraging dependencies on non-official Docker Hub images, given their recent changes to both rate limits and retention.

praveenperera commented 4 years ago

For what its work I've been using ekidd/rust-musl-builder as my builder.

Here is an example:

FROM ekidd/rust-musl-builder:stable as builder

ENV APP=my-app

RUN mkdir .cargo src

COPY Cargo.toml Cargo.toml
COPY Cargo.lock Cargo.lock

RUN echo "fn main() {println!(\"if you see this, the build broke\")}" > src/lib.rs && \
    cargo vendor > .cargo/config && \ 
    cargo build --release && \
    rm -rf src

COPY src src

RUN rm -rf target/release/**/libsrc* 
RUN cargo build --release

FROM alpine:latest

ARG APP_FOLDER=/usr/src/app
ENV APP_USER=appuser

RUN addgroup -S $APP_USER \
    && adduser -S -g $APP_USER $APP_USER

RUN apk update \
    && apk add --no-cache ca-certificates open-ssl \
    && rm -rf /var/cache/apk/*

COPY --from=builder /home/rust/src/target/x86_64-unknown-linux-musl/release/${APP} ${APP_FOLDER}/${APP}
ENV PATH="${APP_FOLDER}:${PATH}"

CMD ["${APP}"]

Replaced the hacky method with [cargo chef]()

FROM ekidd/rust-musl-builder:stable as planner

RUN cargo install cargo-chef

COPY . .
RUN cargo chef prepare --recipe-path recipe.json

FROM ekidd/rust-musl-builder:stable as cacher

RUN cargo install cargo-chef
COPY --from=planner /home/rust/src/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json

FROM ekidd/rust-musl-builder:stable as builder

COPY . .
COPY --from=cacher /home/rust/src/target target
COPY --from=cacher /home/rust/.cargo /home/rust/.cargo

RUN cargo build --release

FROM alpine:latest

ENV APP=my-app
ARG APP_FOLDER=/usr/src/app
ENV APP_USER=appuser

RUN addgroup -S $APP_USER \
    && adduser -S -g $APP_USER $APP_USER

RUN apk update \
    && apk add --no-cache ca-certificates \
    && rm -rf /var/cache/apk/*

COPY --from=builder /home/rust/src/target/x86_64-unknown-linux-musl/release/${APP} ${APP_FOLDER}/${APP}
ENV PATH="${APP_FOLDER}:${PATH}"

CMD ${APP}