はじめに
「Dockerでビルドすると遅いんだよね」「イメージが2GB超えちゃって…」
そんな会話はもう過去の話です。2025年、コンテナ化は劇的に進化しました。Rustも例外ではありません。cargo-chefとBuildKitキャッシュマウントの組み合わせでビルド時間を5-10倍短縮、2.63GBのイメージをdistrolessイメージで約50MB、musl静的リンクならわずか1.7MBという値を達成できます。
この記事では、実践的なDockerfileパターンとベンチマーク結果を詳しく解説します。
実際に検証したAxum Webアプリケーションでは、distroless版で50.3MB、musl+scratch版で1.71MBを達成しました。中規模プロジェクト(約500の依存関係)での初回ビルドは10分、コード変更後の再ビルドはわずか40秒です。
信じられないかもですが、これが2025年の現実です。ちゃんとやれって話です。あと皆さんのDockerfileも教えて欲しいです。
このブログが良ければ読者になったり、nwiizoのXやGithubをフォローしてくれると嬉しいです。では、早速はじめていきます。
2025年の重要なアップデート
Rust 2024 Edition(2025年2月20日リリース)
Rust 1.85.0でRust 2024 Editionが安定版になりました。Docker環境でRust 1.85以降を使えば、Edition 2024の機能が使えます。
Docker関連の進化
- Docker Engine v28:コンテナネットワーキングのセキュリティ強化、AMD GPUサポート docs.docker.com
- docker init GA:Rustプロジェクト用の最適化されたDockerfile自動生成 docs.docker.com
- Docker Bake GA:複雑なビルド設定の宣言的管理 docs.docker.com
- BuildKit 0.25.1:Git URLクエリパラメータ、シークレットの環境変数化など新機能 github.com
基本的な考え方
マルチステージビルドは前提条件
2025年でマルチステージビルドを使わないのは、正直あり得ません。
まずメンテナンス性が格段に向上します。最終的な成果物以外ではサイズを意識したトリッキーな記述が不要になるため、Dockerfileの可読性が劇的に良くなります。次にビルド速度のアップ。並列化、キャッシュマウント、tmpfsなど最適化オプションが豊富に使えるようになり、ビルドパイプライン全体が高速化します。そして何よりセキュリティの向上。シークレット管理の仕組みが標準化され、機密情報の取り扱いが安全になりました。
COPYは最小限に、--mountを活用
COPYが登場するのは、実質的に2つの場面だけです。マルチステージビルドで別ステージから成果物を持ってくる場合と、最終ステージでアプリケーションバイナリをコピーする場合。それ以外、特にソースコードのビルド時には--mount=type=bindを使用します。
必ず記述すべきおまじない
# syntax=docker/dockerfile:1
この1行を必ず先頭に記述します。最新のDockerfile構文が自動的に利用され、新機能が使えるようになります。
2025年のDockerfileはこれでやります
前置きはこれくらいにして、実際のコードを見ていきましょう。
これが2025年のRust標準Dockerfileです。cargo-chefによる依存関係の分離、BuildKitキャッシュマウント、distrolessイメージ、非rootユーザー実行。この記事で解説してきたベストプラクティスのすべてが、この1つのテンプレートに詰め込まれています。
# syntax=docker/dockerfile:1 ARG RUST_VERSION=1.85 ARG APP_NAME=myapp # cargo-chefを使った依存関係キャッシング FROM lukemathwalker/cargo-chef:latest-rust-${RUST_VERSION} AS chef WORKDIR /app FROM chef AS planner COPY . . RUN cargo chef prepare --recipe-path recipe.json FROM chef AS builder # 依存関係のビルド(キャッシュ可能) COPY --from=planner /app/recipe.json recipe.json RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked \ --mount=type=cache,target=/usr/local/cargo/git,sharing=locked \ cargo chef cook --release --recipe-path recipe.json # アプリケーションのビルド COPY . . RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked \ --mount=type=cache,target=/usr/local/cargo/git,sharing=locked \ --mount=type=cache,target=/app/target,sharing=locked \ cargo build --release --bin ${APP_NAME} && \ cp ./target/release/${APP_NAME} /bin/server # テストステージ(オプション) FROM chef AS test COPY . . RUN --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=/usr/local/cargo/git \ cargo test # 本番ステージ:distroless FROM gcr.io/distroless/cc-debian12:nonroot AS runtime COPY --from=builder /bin/server /app/ WORKDIR /app EXPOSE 8000 ENTRYPOINT ["/app/server"]
このDockerfileの主な特徴
- cargo-chefによる依存関係の分離とキャッシング
- BuildKitキャッシュマウントでレイヤーを跨いだキャッシュ
- distrolessによる最小サイズと高セキュリティ
- 非rootユーザー(
:nonrootタグ)での実行 - オプショナルなテストステージ
ビルド最適化の3つの柱
1. cargo-chef
cargo-chefは、Rustの依存関係管理をDockerレイヤーキャッシュに適合させる画期的なツールです。依存関係のコンパイルとソースコードのコンパイルを完全に分離します。
動作メカニズム(2段階):
cargo chef prepare:Cargo.tomlとCargo.lockを解析してrecipe.jsonを作成cargo chef cook:最小限のプロジェクト構造を再構築して依存関係のみをビルド
重要:同じRustバージョンと作業ディレクトリを全ステージで使用すること。異なるバージョンを使うとキャッシュが無効化されます。
実測データ:
- cargo-chefのみで55%の改善
- cargo-chef + sccacheで79%の改善(34秒→7秒)
- 商用プロジェクト(14,000行、500依存関係)で10分→2分
2. BuildKitキャッシュマウント
BuildKitのキャッシュマウント(Docker 18.09以降)を使うと、レイヤー無効化を超えて永続化するキャッシュボリュームが利用できます。
3つの重要なキャッシュポイント:
RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked \ --mount=type=cache,target=/usr/local/cargo/git,sharing=locked \ --mount=type=cache,target=/app/target,sharing=locked \ cargo build --release
/usr/local/cargo/registry:crates.ioからのダウンロード/usr/local/cargo/git:Git依存関係/app/target:ビルド成果物
sharing=lockedパラメータは排他アクセスを保証し、パッケージマネージャーの破損を防ぎます。
CI環境でのキャッシュ共有:
# GitHub Actions - uses: docker/build-push-action@v6 with: cache-from: type=gha cache-to: type=gha,mode=max
パフォーマンスベンチマーク:
- ベースライン:90.60秒
- BuildKitキャッシュマウント:15.63秒(5.8倍高速)
- cargo-chef:18.81秒(4.8倍高速)
- 三位一体(chef + BuildKit + sccache):7-12秒(7.5-13倍高速)
3. sccache
sccache(v0.7.x)はMozilla製のccache風コンパイララッパーで、個々のコンパイル成果物を細粒度でキャッシュします。
FROM rust:1.85 AS builder # sccacheのインストールと設定 RUN cargo install sccache --version ^0.7 ENV RUSTC_WRAPPER=sccache \ SCCACHE_DIR=/sccache \ CARGO_INCREMENTAL=0 WORKDIR /app RUN --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=$SCCACHE_DIR,sharing=locked \ --mount=type=bind,target=. \ cargo build --release
重要:CARGO_INCREMENTAL=0は必須。インクリメンタルコンパイルとsccacheは競合します。
キャッシュヒット率:
- 初回ビルド:0%
- ソースコード変更のみ:85-95%
- 依存関係を更新した時:60-75%
注意点: sccacheの効果は環境によって大きく異なります。一部の環境では効果が薄く、逆にオーバーヘッドとなる場合があります。自環境でのベンチマークが必須です。
イメージサイズの最適化:ベースイメージ選択戦略
ビルドステージ:rust:slim推奨
2025年はrust:slim(Debian系)でよいと思っています。
FROM rust:1.85-slim-bookworm AS builder
理由はシンプルです。Debian stable(bookworm)ベースでglibcを使用しているため、広範な互換性とマルチスレッドワークロードでの優れたパフォーマンスを発揮します。完全版のrust:latestが624MBもあるのに対し、rust:slimはコンパイルに必要な最小限のパッケージだけを含んでいます。無駄がありません。
rust:alpineは避けてください。 muslの互換性問題に加えて、マルチスレッドアプリケーションで最大30倍のパフォーマンス劣化が報告されています。イメージサイズの小ささに惹かれる気持ちはわかりますが、本番環境でこの劣化は致命的です。

最終ステージ:distroless推奨
gcr.io/distroless/cc-debian12が2025年の標準です。
FROM gcr.io/distroless/cc-debian12:nonroot
distrolessの特徴:
- サイズ:21-29MB
- glibc、SSL証明書、タイムゾーンデータ、/etc/passwdを含む
- パッケージマネージャー、シェル不要なバイナリを完全排除
- SLSA 2準拠、cosign署名検証が可能
- CVEスキャンで従来イメージより50-80%少ない脆弱性
:nonrootタグでUID 65534(nobody)として非rootで実行
イメージサイズ比較(実測値)
| イメージ構成 | サイズ | 用途 | 特徴 |
|---|---|---|---|
| scratch + musl(実測) | 1.71MB | CLIツール最小化 | 完全静的リンク |
| distroless/static | 2-3MB | 静的リンクバイナリ | 最小限のファイル |
| distroless/cc-debian12(実測) | 50.3MB | Webアプリ推奨 | glibc |
| debian-slim | 80-120MB | フル互換性 | デバッグツールあり |
| rust:latest(未最適化) | 2.63GB | 開発専用 | ビルドツール込み |
実測削減率:
- rust:latest(2.63GB)→ distroless(50.3MB):98.1%削減
- rust:latest(2.63GB)→ musl+scratch(1.71MB):99.9%削減
静的リンク vs 動的リンク
musl(x86_64-unknown-linux-musl)での静的リンク:
FROM rust:1.85-alpine AS builder RUN apk add --no-cache musl-dev WORKDIR /app # 依存関係のキャッシュ COPY Cargo.toml Cargo.lock ./ RUN --mount=type=cache,target=/usr/local/cargo/registry \ mkdir src && echo "fn main() {}" > src/main.rs && \ cargo build --release --target x86_64-unknown-linux-musl && \ rm -rf src # アプリケーションのビルド COPY src ./src RUN --mount=type=cache,target=/usr/local/cargo/registry \ cargo build --release --target x86_64-unknown-linux-musl FROM scratch COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/myapp /myapp ENTRYPOINT ["/myapp"]
利点:
- 依存関係ゼロで完全にポータブル
- scratchコンテナで実行可能
- イメージサイズ5-10MB
欠点:
- シングルスレッドで0.9-1.0倍、マルチスレッドで0.03-0.5倍のパフォーマンス
- 一部依存関係でsegfaultのリスク
本番環境の推奨:
- 複雑なアプリケーション(Webサーバー、DB接続):glibc + distroless/cc-debian12
- シンプルなCLIツール:musl + scratchを検討
- パフォーマンスが重要:必ずglibcを使用
マルチアーキテクチャビルド
linux/amd64とlinux/arm64の両対応が2025年の標準要件です。
cargo-zigbuild:セットアップゼロのクロスコンパイル
cargo-zigbuild(v0.20.1)はZigツールチェインを使い、セットアップ不要でクロスコンパイルできます。
# syntax=docker/dockerfile:1 ARG RUST_VERSION=1.85 FROM --platform=$BUILDPLATFORM rust:${RUST_VERSION}-alpine AS builder WORKDIR /app # Zigとcargo-zigbuildのインストール RUN apk add --no-cache musl-dev openssl-dev zig RUN cargo install --locked cargo-zigbuild # ターゲットの設定 ARG TARGETPLATFORM RUN case ${TARGETPLATFORM} in \ "linux/amd64") echo x86_64-unknown-linux-musl > /rust_target ;; \ "linux/arm64") echo aarch64-unknown-linux-musl > /rust_target ;; \ esac && \ rustup target add $(cat /rust_target) # 依存関係とビルド COPY Cargo.toml Cargo.lock ./ RUN --mount=type=cache,target=/usr/local/cargo/registry \ mkdir src && echo "fn main() {}" > src/main.rs && \ cargo zigbuild --release --target $(cat /rust_target) && \ rm -rf src COPY src ./src RUN --mount=type=cache,target=/usr/local/cargo/registry \ cargo zigbuild --release --target $(cat /rust_target) FROM alpine:latest ARG TARGETPLATFORM COPY --from=builder /app/target/*/release/app /app CMD ["/app"]
重要:--platform=$BUILDPLATFORMを使うと、ビルド自体はネイティブアーキテクチャで実行できるので、QEMUエミュレーションより圧倒的に速いです(QEMUエミュレーションは16-25倍遅い)。
実測データ:
Docker buildxでのマルチプラットフォームビルド
# ビルダーの作成
docker buildx create --name container-builder \
--driver docker-container --bootstrap --use
# マルチプラットフォームビルド
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t myimage:latest \
--push .
https://docs.docker.com/build/buildx/docs.docker.com
セキュリティベストプラクティス
1. 非rootユーザーで実行
distroless :nonrootタグが最も簡単:
FROM gcr.io/distroless/cc-debian12:nonroot COPY --from=builder /app/target/release/myapp /usr/local/bin/ CMD ["/usr/local/bin/myapp"]
自動的にUID 65534(nobody)として実行されます。
カスタムユーザー作成:
FROM debian:bookworm-slim ARG UID=10001 RUN adduser \ --disabled-password \ --gecos "" \ --home "/nonexistent" \ --shell "/sbin/nologin" \ --no-create-home \ --uid "${UID}" \ appuser USER appuser COPY --from=builder /app/target/release/myapp /app/ CMD ["/app/myapp"]
2. 脆弱性スキャン
Trivy(推奨):
# イメージスキャン
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image myapp:latest
# CI/CD統合
- name: Run Trivy scan
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
severity: 'CRITICAL,HIGH'
exit-code: '1'
distrolessのセキュリティ優位性:
- Alpine(musl)からChiseled Ubuntu(glibc)への移行で30+ CVEが0 CVEに
- distrolessイメージはAlpineより50-80%少ないCVE
- パッケージマネージャー不在により攻撃ベクトル削減
- SLSA 2準拠、cosign署名認証
3. シークレット管理
絶対に避けるべき:環境変数へのシークレット設定
イメージに焼き込まれてしまいます。
正しい方法:
# ビルド時シークレット RUN --mount=type=secret,id=api_token,env=API_TOKEN \ cargo build --release
# 実行時 docker build --secret id=api_token,env=API_TOKEN .
4. イメージバージョンのピン留め
# ❌ 避けるべき FROM rust:latest # ✅ 推奨 FROM rust:1.85-slim-bookworm
ユースケース別Dockerfile
Webアプリケーション(Axum / Actix-web)
上記の「標準Dockerfile」パターンをそのまま使用できます。
CLIツール(完全静的リンク)
# syntax=docker/dockerfile:1 FROM rust:1.85-alpine AS builder WORKDIR /app RUN apk add --no-cache musl-dev openssl-dev openssl-libs-static # 依存関係のキャッシュ COPY Cargo.toml Cargo.lock ./ RUN --mount=type=cache,target=/usr/local/cargo/registry \ mkdir src && echo "fn main() {}" > src/main.rs && \ cargo build --release --target x86_64-unknown-linux-musl && \ rm -rf src COPY src ./src RUN --mount=type=cache,target=/usr/local/cargo/registry \ cargo build --release --target x86_64-unknown-linux-musl FROM scratch COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/cli-tool /app/ ENTRYPOINT ["/app/cli-tool"]
シェルエイリアスは以下のように設定できます。
alias my-cli='docker run --rm -v $(pwd):/data my-cli-image'
ワークスペース(モノレポ)対応
# syntax=docker/dockerfile:1 ARG SERVICE_NAME=api-gateway ARG RUST_VERSION=1.85 FROM lukemathwalker/cargo-chef:latest-rust-${RUST_VERSION} AS chef WORKDIR /app FROM chef AS planner COPY . . RUN cargo chef prepare --recipe-path recipe.json FROM chef AS builder ARG SERVICE_NAME COPY --from=planner /app/recipe.json recipe.json RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked \ --mount=type=cache,target=/usr/local/cargo/git,sharing=locked \ cargo chef cook --release --bin ${SERVICE_NAME} --recipe-path recipe.json COPY . . RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked \ --mount=type=cache,target=/app/target,sharing=locked \ cargo build --release --bin ${SERVICE_NAME} && \ cp ./target/release/${SERVICE_NAME} /bin/service FROM gcr.io/distroless/cc-debian12:nonroot COPY --from=builder /bin/service /app/ ENTRYPOINT ["/app/service"]
異なるサービスを同じDockerfileから生成できます。
docker build --build-arg SERVICE_NAME=api-gateway -t gateway . docker build --build-arg SERVICE_NAME=user-service -t users .
実践的な検証結果
実際のAxum Webアプリケーション(依存関係82個)で3つの戦略を検証しました。
検証環境:
3つのパターン比較
パターン1: Naive(最適化なし)- デフォルトの実態
Dockerfile.naive は何も工夫しないシンプルなビルドです。これが「デフォルトの何もしていない状態」です。
⚠️ デフォルト状態のビルド結果
- 初回ビルド時間: 約10-15分(依存関係82個を全てコンパイル)
- ソースコード変更後の再ビルド: 約10-15分(依存関係も毎回再コンパイル)
- 最終イメージサイズ: 2.63GB
- セキュリティ: rootユーザー、開発ツール込み(脆弱性大)
問題点:
- ソースコード1行変更するだけで10-15分のビルドが毎回走る
- イメージに不要なRustコンパイラ(500MB)、ビルドツール、ドキュメントが全て含まれる
- マルチステージビルドがないため、最終イメージが巨大
- cargo-chefがないため、依存関係とソースコードが分離されていない
パターン2: Baseline(cargo-chef + distroless)
Dockerfile は2025年の推奨パターンです。
ビルド結果
- ビルド時間: 38秒(依存関係キャッシュ済み)
- 最終イメージサイズ: 50.3MB
- セキュリティ: 非rootユーザー(UID 65534)、最小限のファイル
- Trivy脆弱性: 0 HIGH/CRITICAL
パターン3: Ultra-minimal(musl + scratch)
Dockerfile.musl は最小サイズを優先したパターンです。
ビルド結果
- ビルド時間: 46秒(依存関係キャッシュ済み)
- 最終イメージサイズ: 1.71MB
- セキュリティ: rootユーザー(scratchに制限あり)
比較結果まとめ
| 項目 | Naive (未最適化) | Baseline (distroless) | Ultra-minimal (musl) |
|---|---|---|---|
| イメージサイズ | 2.63GB | 50.3MB | 1.71MB |
| 削減率 | - (100%) | 98.1%削減 | 99.9%削減 |
| ビルド時間 | 30秒 | 38秒 | 46秒 |
| マルチステージ | ❌ なし | ✅ あり (4段階) | ✅ あり (2段階) |
| キャッシュ最適化 | ❌ なし | ✅ cargo-chef + BuildKit | ✅ BuildKit |
| ベースイメージ | rust:1.85 (full) | distroless/cc-debian12 | scratch |
| リンク方式 | 動的(glibc) | 動的(glibc) | 静的(musl) |
| 開発ツール | ❌ 含まれる | ✅ 除去済み | ✅ 除去済み |
| セキュリティ | ❌ 低 | ✅ 高 | ⚠️ 中 |
| デバッグ | ✅ 可能 | ❌ 困難 | ❌ 不可能 |
パフォーマンスベンチマーク
商用プロジェクト(14,000行、500依存関係):
- 最適化なし:10分
- cargo-chef使用:2分(5倍高速化)
大規模ワークスペース(400 crate、1500依存関係):
- 未最適化:約65分
- 最適化後:約2分(30倍以上の改善)
検証の再現方法
このリポジトリで実際に試せます。
# Baseline版のビルド docker build -t rust-demo:baseline . # Ultra-minimal版のビルド docker build -f Dockerfile.musl -t rust-demo:musl . # サイズ比較 docker images | grep rust-demo # 動作確認 docker run -p 8000:8000 rust-demo:baseline docker run -p 8001:8000 rust-demo:musl
よくある問題と解決策
OpenSSLリンクエラー
エラー: "Could not find directory of OpenSSL installation"
解決策1:vendored OpenSSL(最も簡単)
[dependencies]
openssl = { version = "0.10", features = ["vendored"] }
解決策2:Alpine適切パッケージ
FROM rust:1.85-alpine RUN apk add --no-cache openssl-dev openssl-libs-static musl-dev
解決策3:Debianベース使用
FROM rust:1.85-slim-bookworm RUN apt-get update && apt-get install -y pkg-config libssl-dev
解決策4:rustls(Rust-native TLS)
[dependencies]
reqwest = { version = "0.11", features = ["rustls-tls"], default-features = false }
muslリンクエラー
Alpine向け:
FROM rust:1.85-alpine RUN apk add musl-dev openssl-dev openssl-libs-static RUN rustup target add x86_64-unknown-linux-musl ENV PKG_CONFIG_ALLOW_CROSS=1 RUN cargo build --release --target x86_64-unknown-linux-musl
必要な環境変数:
RUSTFLAGS='-C target-feature=+crt-static'PKG_CONFIG_ALLOW_CROSS=1OPENSSL_STATIC=1(システムOpenSSL使用時)
DNS解決エラー(scratchイメージ)
解決策1:distroless/static使用
FROM gcr.io/distroless/static-debian12
[dependencies]
reqwest = { version = "0.11", features = ["trust-dns"] }
解決策3:必要ファイルコピー
FROM alpine:latest AS ca-certificates RUN apk add -U --no-cache ca-certificates FROM scratch COPY --from=ca-certificates /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
.dockerignoreの重要性
.dockerignoreがないと、target/ディレクトリ(数GB)がビルドコンテキストに含まれ、ビルドが遅くなります。
# .dockerignore target/ .git/ .env *.log
効果: ビルドコンテキストのサイズを数GBから数MBに削減 → ビルド開始が高速化。
イメージサイズ肥大化
一般的原因と解決策:
- 最終イメージにビルドツール含む → マルチステージビルドで93%削減
- 本番環境でfull rustイメージを使用 → slimランタイムベースで95%削減
- バイナリにデバッグシンボルが含まれる →
strip target/release/myappで30-40%削減 - 開発依存関係 → プロファイル設定
[profile.release] strip = true lto = true codegen-units = 1
2025年の新ツール活用
docker init - プロジェクトの素早い立ち上げ
# プロジェクトディレクトリで実行 docker init # Rustを選択すると自動生成: # - Dockerfile # - compose.yaml # - .dockerignore # - README.Docker.md
Docker Bake - 複雑なビルドの管理
docker-bake.hcl:
group "default" { targets = ["app"] } variable "TAG" { default = "latest" } target "app" { context = "." dockerfile = "Dockerfile" tags = ["myapp:${TAG}"] platforms = ["linux/amd64", "linux/arm64"] cache-from = ["type=registry,ref=myapp:cache"] cache-to = ["type=registry,ref=myapp:cache,mode=max"] }
# 実行 docker buildx bake # 変数をオーバーライド docker buildx bake --set TAG=v1.0.0
おわりに
この記事では、2025年時点でのRust Dockerのベストプラクティスを包括的に解説しました。cargo-chefによる依存関係の分離キャッシング、BuildKitの永続キャッシュマウント、distrolessイメージによるセキュリティ強化という3つの柱を中心に、実践的なDockerfileパターンと実測データを提供しています。
Rustのコンテナ化は長い間「ビルドが遅い」「イメージが大きい」という課題を抱えていました。コンパイル時間の長さは諦めるしかなく、数GBのイメージサイズは「Rustだから仕方ない」と言われてきました。
しかし、2025年現在、その課題は完全に解決しました。適切な最適化で、ビルド時間を5-10倍短縮、イメージサイズを98-99%削減できます。これは単なる理論ではなく、実際のプロダクション環境で日々使われている技術です。
2025年のゴールデンルール
この記事で紹介した技術を実践する際は、以下の10のポイントを押さえておくといいでしょう。
# syntax=docker/dockerfile:1を必ず記述 - 最新のDockerfile構文を自動利用- cargo-chefで依存関係を分離 - 5-10倍のビルド高速化を実現
- BuildKitキャッシュマウントを活用 - レイヤーを超える永続的なキャッシュ
- distroless/cc-debian12:nonrootを使用 - 50MB、非root、高セキュリティ
- rust:slim-bookwormでビルド - Alpineは避ける(マルチスレッド性能問題)
RUN --mount=type=bindでソースコードをマウント - COPYの最小化- マルチステージビルドは必須 - 2025年の前提条件
- 非rootユーザーで実行 - セキュリティの基本原則
- TrivyまたはGrypeでスキャン - 継続的なセキュリティ検証
- イメージバージョンをピン留め -
:latestは避ける
大半の本番ワークロードには、glibc + distroless/cc-debian12 + cargo-chefの組み合わせが最適解です。この構成により、50MBの小サイズ、2分の高速ビルド、フルパフォーマンス、優れたセキュリティプロファイルを実現できます。
マルチスレッドアプリケーションでmuslを使う場合、1点だけ注意が必要です。最大30倍のパフォーマンス劣化リスクがあるので、本番環境への導入前に必ずベンチマークで検証しましょう。イメージサイズだけで判断すると、後で後悔します。
2025年のRust Dockerは、従来の課題を完全に克服しました。高速、小サイズ、セキュア、マルチアーキテクチャ対応の成熟した技術スタックになっています。この記事で紹介した標準Dockerfileパターンは、そのままプロダクション環境で使える構成です。まずは標準パターンから始めて、必要なら sccache や cargo-zigbuild などの高度な最適化を追加するといいでしょう。
Rustエコシステムの進化とDockerの機能強化で、今後もさらに改善していくはずです。この記事が、あなたのRustアプリケーションのコンテナ化に役立てば嬉しいです。