$30 off During Our Annual Pro Sale. View Details »

Rust、何もわからない... #2

Rust、何もわからない... #2

「Rust、何もわからない... 」

チュートリアルを読んで完全に理解したつもりでも、実務で使ってみると次々とこれはどうすればいいのか、という場面が出てきます。本イベントは実務で得た知見を共有する中級者向けのイベントです。
今回は、ゲストにキャディ株式会社 Tech Leadのvaaaaanquishさんに来ていただき、CADDiの事例も共有していただきます。

日時:5/19(木) 19:00~20:00
イベントハッシュタグ:#Rust何もわからない

estie | エスティ

May 24, 2022
Tweet

More Decks by estie | エスティ

Other Decks in Programming

Transcript

  1. 使うぜ!Cargo workspace!
    @kenkoooo

    View Slide

  2. kenkoooo
    ● @kenkoooo
    ● NII→リクルート→SoundHound→Indeed→estie
    ● estieでRustでアプリ作ってます!
    ● 競プロやってます!

    View Slide

  3. 今日話すこと
    1. Cargo workspaceとは?
    2. Workspaceでdocker build

    View Slide

  4. Cargo workspace とは?

    View Slide

  5. ディレクトリ構成の変化
    backend/
    ├── api
    ├── auth0
    ├── datadog
    ├── middleware
    │ └── src
    │ ├── auth
    │ ├── datadog
    ├── s3
    ├── sendgrid
    ├── sql
    ├── src
    ├── tests
    ├── Cargo.lock
    └── Cargo.toml
    backend/
    ├── src
    │ ├── api
    │ ├── datadog
    │ ├── db
    │ ├── middleware
    │ │ ├── auth
    │ │ └── datadog
    │ ├── s3
    │ └── service
    ├── tests
    ├── Cargo.lock
    └── Cargo.toml
    初期の頃の構成 現在の構成

    View Slide

  6. 基本のプロジェクト構成を思い出す

    View Slide

  7. Rustプロジェクトの基本構成
    app/
    ├── src
    │ ├── module1
    │ ├── module2
    │ │ ├── sub_module1
    │ │ └── sub_module2
    │ └── module3
    ├── Cargo.lock
    └── Cargo.toml
    ● プロジェクトのルートには
    ○ src/
    ○ Cargo.toml
    ○ Cargo.lock
    ● 各モジュールは src/ の中に入っている

    View Slide

  8. Rustプロジェクトの基本構成
    module1
    crate
    module2
    sub_module1
    sub_module2

    View Slide

  9. Rustプロジェクトの基本構成
    module
    crate
    sub_module
    pub struct Struct1;
    pub(crate) struct Struct2;
    pub(super) struct Struct3;

    View Slide

  10. Rustプロジェクトの基本構成
    module
    crate
    sub_module
    pub struct Struct1;
    pub(crate) struct Struct2;
    pub(super) struct Struct3;

    View Slide

  11. Rustプロジェクトの基本構成
    module
    crate
    sub_module
    pub struct Struct1;
    pub(crate) struct Struct2;
    pub(super) struct Struct3;
    ライブラリではなくアプリを作るとき、 pub
    かどうかはそんなに重要ではない …

    View Slide

  12. Rustプロジェクトの基本構成
    module
    crate
    sub_module
    pub(crate) struct Struct2;
    pub(super) struct Struct3;

    View Slide

  13. Rustプロジェクトの基本構成
    module
    crate
    sub_module
    pub(crate) struct Struct2;
    結局、全開にしているのと
    ほぼ同じ状況に……

    View Slide

  14. お気持ち
    ● ある役割の単位(api, sql など)の中では全開にしたい
    ● その単位の外からのアクセスは限定したい

    View Slide

  15. Cargo workspace を使うとどうなる?

    View Slide

  16. Rustプロジェクトの基本構成
    module1
    crate
    module2
    sub_module1
    sub_module2

    View Slide

  17. Workspaceの世界
    module1
    crate
    module2
    sub1
    sub2
    module1
    crate
    module2
    sub1
    sub2

    View Slide

  18. Rustプロジェクトの基本構成
    module
    crate
    sub_module
    pub struct Struct1;
    pub(crate) struct Struct2;
    pub(super) struct Struct3;

    View Slide

  19. Rustプロジェクトの基本構成
    module
    crate (SQLなどの1機能のモジュール)
    sub_module
    pub struct Struct1;
    pub(crate) struct Struct2;
    pub(super) struct Struct3;

    View Slide

  20. Rustプロジェクトの基本構成
    module
    crate (SQLなどの1機能のモジュール)
    sub_module
    pub struct Struct1;
    pub(crate) struct Struct2;

    View Slide

  21. Rustプロジェクトの基本構成
    module
    crate (SQLなどの1機能のモジュール)
    sub_module
    pub struct Struct1;
    pub(crate) struct Struct2;
    機能単位の中では全開・外には出さない
    外に見せるインターフェイスとなる

    View Slide

  22. Workspace の良さ
    ● 普通のアプリを作る分には「親mod」みたいな感じ
    ● とりあえず pub(crate) でやっても酷いことにはならない
    ● 各 crate の lib.rs がインターフェイスになる

    View Slide

  23. Workspace の設定方法

    View Slide

  24. app/
    ├── Cargo.lock
    ├── Cargo.toml
    └── src
    ├── lib.rs
    ├── module1
    │ └── sub_module.rs
    └── module1.rs
    app/
    ├── Cargo.lock
    ├── Cargo.toml
    ├── module1
    │ ├── Cargo.toml
    │ └── src
    │ ├── sub_module.rs
    │ └── lib.rs
    └── src
    └── lib.rs

    View Slide

  25. ルートの Cargo.toml を設定
    [package]
    name = "application"
    version = "0.1.0"
    edition = "2021"
    [dependencies]
    [workspace]
    members = ["module1"]

    View Slide

  26. テスト
    いつもの
    cargo test
    Workspace では
    cargo test --workspace

    View Slide

  27. まとめ
    ● Workspace で、プロジェクト内に小さい crate をポコポコ作れる
    ● Visibility をまあまあ雑に設定できる

    View Slide

  28. Workspace で docker build

    View Slide

  29. Rust プロジェクトのdocker build事情
    ● Dockerでキャッシュを効かせるのが大変!
    ● まず Cargo.toml と Cargo.lock だけコピーする
    ● ビルドを走らせ、依存パッケージのコンパイルをする
    ———————— ここまでキャッシュされる ———————
    ● コードをコピーして再度ビルドする
    ○ アプリ部分のみコンパイルして、最後にリンク

    View Slide

  30. app/
    ├── Cargo.lock
    ├── Cargo.toml
    └── src
    ├── lib.rs
    ├── module1
    │ └── sub_module.rs
    └── module1.rs
    app/
    ├── Cargo.lock
    ├── Cargo.toml
    ├── module1
    │ ├── Cargo.toml
    │ └── src
    │ ├── sub_module.rs
    │ └── lib.rs
    └── src
    └── lib.rs

    View Slide

  31. app/
    ├── Cargo.lock
    ├── Cargo.toml
    └── src
    ├── lib.rs
    ├── module1
    │ └── sub_module.rs
    └── module1.rs
    app/
    ├── Cargo.lock
    ├── Cargo.toml
    ├── module1
    │ └── Cargo.toml
    ├── module2
    │ └── Cargo.toml
    ├── module3
    │ └── Cargo.toml
    └── src
    └── lib.rs

    View Slide

  32. app/
    ├── Cargo.lock
    ├── Cargo.toml
    └── src
    ├── lib.rs
    ├── module1
    │ └── sub_module.rs
    └── module1.rs
    app/
    ├── Cargo.lock
    ├── Cargo.toml
    ├── module1
    │ └── Cargo.toml
    ├── module2
    │ └── Cargo.toml
    ├── module3
    │ └── Cargo.toml
    ├── module4
    │ └── Cargo.toml
    ├── module5
    │ └── Cargo.toml
    Cargo.toml 多すぎ!

    View Slide

  33. Rust プロジェクトのdocker build事情
    ● まず Cargo.toml と Cargo.lock だけコピーする
    ● ビルドを走らせ、依存パッケージのコンパイルをする
    ———————— ここまでキャッシュされる ———————
    ● コードをコピーして再度ビルドする
    ○ アプリ部分のみコンパイルして、最後にリンク

    View Slide

  34. Rust プロジェクトのdocker build事情
    ● まず Cargo.toml と Cargo.lock だけコピーする
    ● ビルドを走らせ、依存パッケージのコンパイルをする
    ———————— ここまでキャッシュされる ———————
    ● コードをコピーして再度ビルドする
    ○ アプリ部分のみコンパイルして、最後にリンク
    Cargo.tomlが多すぎて
    最高のDockerfileが作れない!

    View Slide

  35. cargo-chef のご案内

    View Slide

  36. cargo-chef
    https://crates.io/crates/cargo-chef
    ● Rust で良い感じに Docker イメージをビルドするツール
    ● Dockerfile がシュッとする

    View Slide

  37. RUN mkdir -p s3/src
    RUN touch s3/src/lib.rs
    COPY ./s3/Cargo.toml ./s3/
    RUN mkdir -p api/src
    RUN touch api/src/lib.rs
    COPY ./api/Cargo.toml ./api/
    RUN mkdir -p pidan/src
    RUN touch pidan/src/lib.rs
    COPY ./pidan/Cargo.toml ./pidan/
    RUN mkdir -p datadog/src
    RUN touch datadog/src/lib.rs
    COPY ./datadog/Cargo.toml ./datadog/
    RUN mkdir -p sendgrid/src
    RUN touch sendgrid/src/lib.rs
    COPY ./sendgrid/Cargo.toml ./sendgrid/
    RUN mkdir -p firehose/src
    RUN touch firehose/src/lib.rs
    COPY ./firehose/Cargo.toml ./firehose/
    RUN mkdir -p sql/src
    RUN touch sql/src/lib.rs
    COPY ./sql/Cargo.toml ./sql/
    COPY ./Cargo.lock .
    RUN cargo build --release
    RUN rm -rf ./src
    COPY ./src ./src
    RUN touch src/lib.rs
    RUN rm -rf ./s3
    COPY ./s3 ./s3
    RUN touch s3/src/lib.rs
    RUN rm -rf ./api

    View Slide

  38. # cargo-chef の公式イメージを使う
    FROM lukemathwalker/cargo-chef:latest-rust-1.60.0 AS chef
    WORKDIR /app
    # 依存関係を整理したファイル recipe.json を出力する。
    FROM chef AS planner
    COPY . .
    RUN cargo chef prepare --recipe-path recipe.json
    FROM chef AS builder
    # recipe.json に基づいて dependencies をビルドする。recipe.json に変更がなければここまでキャッシュされている。
    COPY --from=planner /app/recipe.json recipe.json
    RUN cargo chef cook --release --recipe-path recipe.json
    # アプリケーションをビルドする
    COPY . .
    RUN cargo build --release
    # プロダクション用の Docker イメージをビルドする
    FROM rust:1.60.0 AS production
    ...

    View Slide

  39. まとめ
    ● Cargo Workspace 最高!
    ● cargo-chef 最高!
    ○ Workspace を使ったプロジェクトでも Dockerfile がシュッとする

    View Slide