📦

WASMアプリをIBM Cloud Code Engineにデプロイしてみた

に公開

はじめに

本記事はサクッとRustプロジェクトをWASMにコンパイルしてコンテナで動かしてみたの続編となります。
今回は通常の Linux コンテナ内で WebAssembly runtime を起動し、.wasm を実行します。
前回(Rancher Desktop の Wasm ランタイム上で FROM scratch の超軽量イメージを動かす)から一歩進めて、同じ Wasm アプリを Code Engine にデプロイしてみたいと思います。

必要ツール

  • Rust 1.85 以上(Edition 2024 対応)
    • rustup 利用を前提
    • wasm32-wasip1
      • % rustup target list --installedで確認可能
  • Spin
  • Docker
  • IBM Cloud CLI + Code Engine プラグイン

手順

1. spin newでRustプロジェクトを作成します。今回はシンプルなAPIを作成するためhttp-rustを選択します。

% spin new
Pick a template to start your application with:
  http-c (HTTP request handler using C and the Zig toolchain)
  http-empty (HTTP application with no components)
  http-go (HTTP request handler using (Tiny)Go)
  http-grain (HTTP request handler using Grain)
  http-js (HTTP request handler using JavaScript)
  http-php (HTTP request handler using PHP)
  http-py (HTTP request handler using Python)
> http-rust (HTTP request handler using Rust)
  http-ts (HTTP request handler using TypeScript)
  http-zig (HTTP request handler using Zig)
  redirect (Redirects a HTTP route)
  redis-go (Redis message handler using (Tiny)Go)
  redis-js (Redis message handler using JavaScript)
  redis-rust (Redis message handler using Rust)
  redis-ts (Redis message handler using TypeScript)
  static-fileserver (Serves static files from an asset directory)

プロジェクト名は今回はhello-wasm-ceとしました、あとはEnterでOKです。

2. .wasm のビルド(ローカル)

rustup target add wasm32-wasip1
cargo build --target wasm32-wasip1 --release
# → ./target/wasm32-wasip1/release/hello_wasm_ce.wasm が生成される想定

.wasm はアーキ非依存!
M1 Mac 上でビルドしたものを、そのまま x86_64 コンテナ内で実行できます。ターゲット名は wasm32-wasip1 に統一しましょう。

3. spin.tomlの更新

spin.tomlを以下のように更新

/// 省略

[component.hello-wasm-ce]
source = "hello_wasm_ce.wasm" # コンテナ内にコピーする wasm の“ファイル名”に合わせる

///

spin.toml の書式(manifest v2)は公式リファレンス参照。 source は“コンテナ内の相対パス” で指定します。

4. Dockerfileの追加

すでにローカルで .wasm を作ってある前提です。Spin バイナリだけ入れて実行します。
生成AIにDockerfile作ってもらいました。
Code Engineは現在WASMをサポートしていないため、通常のLinuxコンテナ内でspin upしてWASMアプリを動かします。

FROM debian:bookworm-slim

ARG SPIN_VERSION=2.4.0
ARG SPIN_ARCH=linux-amd64

RUN apt-get update \
 && apt-get install -y --no-install-recommends ca-certificates curl \
 && rm -rf /var/lib/apt/lists/*

# Install Fermyon Spin CLI (Linux/amd64)
RUN curl -fsSL -o /tmp/spin.tgz \
     https://github.com/fermyon/spin/releases/download/v${SPIN_VERSION}/spin-v${SPIN_VERSION}-${SPIN_ARCH}.tar.gz \
 && tar -xzf /tmp/spin.tgz -C /usr/local/bin spin \
 && rm -f /tmp/spin.tgz \
 && /usr/local/bin/spin --version

RUN useradd -m app
USER app
WORKDIR /app

# ※ spin.toml の component.source が "hello_wasm_ce.wasm" であることを想定
COPY --chown=app:app spin.toml /app/spin.toml
COPY --chown=app:app target/wasm32-wasip1/release/hello_wasm_ce.wasm /app/hello_wasm_ce.wasm

ENV RUST_LOG=info
EXPOSE 8080

# Code Engine provides $PORT (default 8080). Bind Spin to it.
CMD ["/bin/sh","-lc","exec /usr/local/bin/spin up --from /app/spin.toml --listen 0.0.0.0:${PORT:-8080}"]

5. イメージのビルド & プッシュ

IBM Cloud, Container Registoryにログイン

% ibmcloud login -a https://cloud.ibm.com --sso
% ibmcloud cr login

Buildします。
us.icr.ioはリージョンに合わせてください。RESOURCE_GROUPは環境に合わせ、PACKAGEPROJECT, VERSIONは任意です。

% docker build . \
		--platform linux/amd64 \
		-t ${PACKAGE}:latest
% docker tag ${PACKAGE}:latest ${PACKAGE}:${VERSION}
% docker tag ${PACKAGE}:${VERSION} \
		us.icr.io/${RESOURCE_GROUP}/${PROJECT}/be:${VERSION}

Pushします。

% docker push us.icr.io/${RESOURCE_GROUP}/${PROJECT}/be:${VERSION}

以下参照です

6. 動作確認

うまく動きました!

% curl https://hoge.us-south.codeengine.appdomain.cloud/
Hello, Fermyon  

7. WASMにするメリット

  • 強力なサンドボックス(WASIの能力ベース権限)
    ファイルやネットワーク等は「明示的に与えた権限」だけに限定。モジュールはホストOSや他プロセスから隔離され、万一のバグでも被害半径を絞れます。これは“Linuxコンテナの内側”でも効き続ける価値です。

  • 起動の速さ(モジュール初期化が軽い)
    コンテナ自体は必要でも、アプリロジックは Wasm モジュールのロード・実行。JVM/Python等の重量ランタイムより初動が軽くなりやすく、Code Engine のスケールtoゼロ(アイドル時ゼロ→需要で起動)と相性が良いです。低レイテンシが必須なら min-scale や scale-down delay を調整しつつ、Wasm の軽さでコールドスタート影響を抑えやすい。

  • ポータビリティ & 将来性(アーキ非依存+コンポーネントモデル)
    .wasm は OS/CPU を跨いで再配布でき、他の Wasm ホスト(Fermyon Cloud など)にも移しやすい。

  • サプライチェーンの単純化
    実アプリは .wasm だけ更新、ランタイム層(ベースOS+Spin/Wasmtime)は固定化しやすい。結果として更新差分(push/pull)も小さく、脆弱性対応も層を分けて管理できます。

まとめ

WASMエコシステムはまだまだ発展途上ですが、期待できる恩恵も大きいです!
引き続きキャッチアップしていきます📦

Discussion