LoginSignup
2
2

More than 1 year has passed since last update.

CI/CDでRustビルド高速化

Posted at
1 / 25

CI/CDでRustビルド高速化

事前準備

  • プロジェクト作成
cargo init
  • Dockerファイル作成

image.png

  • Dockerビルドコマンドを実行
docker build -f dockerfile .

  • (ビルドしたイメージはAWS ECRなどに入れて、ECSで動けるようにする)
docker push xxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:yyyy

方法1 - Dockerの書き方の改善


  • 一般的なDocker設定ファイルは以下となります

dockerfile_1

FROM rust:latest

WORKDIR /usr/src/myapp

COPY . .

RUN cargo build --release

RUN cargo install --path .

CMD ["/usr/local/cargo/bin/myapp"]


  • Docker ビルド実行して、結果を見ます
docker build -f dockerfile_1 .

image.png


  • Docker ビルドをもう一回実行して、結果を見ます
docker build -f dockerfile_1 .

image.png


  • 結論: 2回目の実行はコードは何も変わらないですので、Dockerビルドは全部キャッシュ使えます。

  • コードをちょっと修正します。 image.png

  • Docker ビルドをもう一回実行して、結果を見ます
docker build -f dockerfile_1 .

image.png


-「Step 3/6」からキャッシュされて、ライブラリーなどダウンロードして、インストールする処理が実行されます。
- コードだけ修正したのに、ライブラリーが再インストールされますので、ビルド時間が発生しました。
- 原因はコード変更されたので、Step 3/6 : COPY . . キャッシュしないので、これ以降はキャッシュできなくなります。
- ライブラリーインストールなので、あまり変わらないので、先にインストールして、キャッシュ効くように修正しないといけません。


  • 具体的には以下のコードです

dockerfile_2

FROM rust:latest

WORKDIR /usr/src/myapp

COPY Cargo.toml Cargo.toml

RUN mkdir src/

RUN echo "fn main() {println!(\"if you see this, the build broke\")}" > src/main.rs

RUN cargo build --release

RUN rm -f target/release/deps/myapp*

COPY . .

RUN cargo build --release

RUN cargo install --path .

CMD ["/usr/local/cargo/bin/myapp"]


  • ビルドして、結果を見ます
docker build -f dockerfile_2 .

image.png


  • コードを修正して、再ビルドして、結果をみます。

image.png

docker build -f dockerfile_2 .

image.png


  • 「Step 6/11 : RUN cargo build --release」にはキャッシュされました。

方法2 - Imageサイズ改善


  • image名を指定して、Dockerビルドして、イメージサイズを確認しましょう
 docker build -t apptest -f dockerfile_2 .

image.png


  • Hello wordの表示だけなのに、イメージサイズは1.4GBがでた
  • イメージサイズは大きくになると、イメージPUSHなどは時間がかかります。
  • Rust言語でビルドしたファイルだけがあれば動けますが、ビルドの時にダウンロードしたライブラリーなどはイメージに入っていますので、サイズは大きいでした。
  • ビルドしたファイルを別のImageに入れると、Imageのサイズは小さくになります。

  • 以下に修正して、再ビルドします。

dockerfile_2

# ------------------------------------------------------------------------------
# Cargo Build Stage
# ------------------------------------------------------------------------------

FROM rust:latest as cargo-build

WORKDIR /usr/src/myapp

COPY Cargo.toml Cargo.toml

RUN mkdir src/

RUN echo "fn main() {println!(\"if you see this, the build broke\")}" > src/main.rs

RUN cargo build --release

RUN rm -f target/release/deps/myapp*

COPY . .

RUN cargo build --release

RUN cargo install --path .


# ------------------------------------------------------------------------------
# Final Stage
# ------------------------------------------------------------------------------

FROM alpine:latest

COPY --from=cargo-build /usr/src/myapp/target/release/myapp /usr/local/bin/myapp

CMD ["myapp"]

 docker build -t apptest -f dockerfile_2 .

 docker image ls

image.png


  • ビルドしたファイルは別のイメージに入れました。 不要なファイルはイメージにないので、イメージのサイズはすごく小さくになりました。

方法3 - クラウドキャッシュを使います。


  • 上の方法はキャッシュ使いますが、キャッシュデータはロカールに置きます。
  • CIでビルドする場合、毎回にビルドRunnerが変わりますので、前回のビルドはキャッシュできません

  • ビルドするイメージをPUSHして、次回のビルドは前のイメージからキャッシュします。
docker build -t xxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:yyyy -f dockerfile_2 .
docker push xxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:yyyy

  • 次回にビルドの時にキャッシュを指定します。
docker build \
    -t xxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:yyyy \
    --cache-from xxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:yyyy \
    -f dockerfile_2 . 

  • 注意: 方法2ではイメージサイズは小さくにしたが、このイメージはビルドイメージではないので、--cache-from 指定しても効かないです。

方法4 - Rustビルドキャッシュ


  • sccacheを使います
  • https://github.com/mozilla/sccache
  • ビルドしたファイルはS3にキャッシュします。
  • ビルドするときに、S3からキャッシュをとって、必要なファイルだけビルドします。
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2