Rust の Docker イメージを小さくする方法
Rust で作ったアプリケーションを Docker でデプロイする際、イメージのサイズが大きくなってしまうことがあります。
今回は、そんな Rust の Docker イメージを小さくする方法をご紹介します。
TL;DR
-
distroless/static
を使うことでイメージサイズを大幅に小さくできる - Rust の公式イメージの Alpine を使えば自動的に static にビルドしてくれる
- 依存 crate をキャッシュしておくために空の main ファイルを作っておく
以下は、実際に使った Dockerfile です。
FROM rust:1.77.2-alpine as builder
RUN apk --no-cache add musl-dev
WORKDIR /app
COPY Cargo.toml .
COPY Cargo.lock .
RUN mkdir src && echo "fn main() {}" > src/main.rs
RUN cargo build --release
COPY src src
RUN touch src/main.rs
RUN cargo build --release
RUN strip target/release/myappname -o main
FROM gcr.io/distroless/static-debian12:nonroot
USER nonroot
WORKDIR /app
COPY /app/main /app/main
ENTRYPOINT [ "/app/main" ]
ビルドには Alpine を使う
Rust の公式イメージには、Alpine ベースのものがあります。
Alpine は軽量な Linux ディストリビューションで、musl-libc を使っています。
Alpine ベースのイメージを使えば、自動的に static にビルドしてくれるので、配備先にライブラリがなくても大丈夫です。
さらに strip コマンドでオブジェクトファイルから余計な情報を削ぎ落としています。
依存 crate をキャッシュする
自分のコードを変えるたびに crate のダウンロードから始まるのは大変です。
そのため、依存 crate をキャッシュしておけるように、2ステップに分け、最初のビルドでは空の main ファイルを作っておくのがよいでしょう。
COPY Cargo.toml .
COPY Cargo.lock .
RUN mkdir src && echo "fn main() {}" > src/main.rs
RUN cargo build --release
こうすることで、依存 crate のビルドがキャッシュされるので、ビルド時間を短縮できます。
distroless/static を使う
Docker イメージを小さくする一番の方法は、不要なものを含めないことです。
そのためには、distroless
の static イメージを使うのが効果的です。
distroless
は、Google が提供しているイメージで、必要最低限のファイルしか含まれていません。
つまり、シェルやパッケージマネージャなどが含まれていないので、イメージサイズを大幅に小さくできるのです。
手元の例では、通常の Rust イメージを使った場合は 99MB だったのが、distroless/static
を使うことで 4.5MB まで小さくなりました。
nonroot ユーザーを使う
セキュリティを向上させるためには、root
ユーザーを使わないことが重要です。
distroless/static
イメージには、nonroot
というユーザーが用意されているので、それを使うのがよいでしょう。
FROM gcr.io/distroless/static-debian12:nonroot
USER nonroot
こうすることで、万が一コンテナ内でプロセスが乗っ取られても、被害を最小限に抑えられます。
まとめ
Rust で作ったアプリケーションの Docker イメージサイズが小さくなれば、デプロイが速くなったり、ストレージの節約になったりと、嬉しいことがたくさんあります。
また、nonroot
ユーザーを使えば、セキュリティ面でも安心です。
ぜひ、みなさんも試してみてください。
Discussion