Slide 1

Slide 1 text

使うぜ!Cargo workspace! @kenkoooo

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

Cargo workspace とは?

Slide 5

Slide 5 text

ディレクトリ構成の変化 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 初期の頃の構成 現在の構成

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

Cargo workspace を使うとどうなる?

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

Workspace の設定方法

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

Workspace で docker build

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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 多すぎ!

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

cargo-chef のご案内

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

# 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 ...

Slide 39

Slide 39 text

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