ここでいうWASMとはWebAssemblyのことを指しています。 WebAssemblyについては説明するのが難しいので、オフィシャルサイトをご覧ください。
かなりざっくり説明すると、特定の環境に依存しないで動くアプリケーションの配布形式の一種です。 初期はJSの高速化、のちにブラウザーでアプリケーションが動くというところから始まりました。 現在は、色々な環境でアプリケーションを動かすための「エンジン」として期待される傾向があります。
Docker DesktopもサポートするプラットフォームとしてWASMランタイムを追加して話題 となっていましたが、この機能は開発リリースでしか利用できませんでした。
Dockerはdockerdとcontainerdが動いていて、役割ごとにdockerdかcontainerdが動作します。
WASMアプリを動かすためのインターフェイスであるcontainerd-wasm-shim
が追加されて、
ランタイムを呼び出すと、そのランタイムを使ってWASMアプリをDockerで動かせるという仕組みです。
以下の表ではwasmedgeランタイムが呼び出されていますが、現在はWasm workloads に書かれているランタイムがサポートされています。
最近それが一般リリースでも使える状況になったため、設定変更すればすぐに手元の環境でも試すことができます。 さっそく触ってみましょう!
Docker Desktopの設定変更
「Use containerd for pulling and storing images」と「Enable Wasm」を設定して、Docker Desktopを再起動するだけです。 初めて「Enable Wasm」を設定した場合は、ランタイムのダウンロードが行われます(一回でダウンロードできないときがあります)。
注意!
執筆日時点ではこの機能を使うために設定を変更すると、VSCodeでDocker拡張機能が使えなくなる点に注意してください。 問題が解決されるまでは「どっちが正常に動くことが自分にとって重要なのか」、考える必要があります。
(VSCodeでDocker拡張機能が使えなくなるので、つまりDev Containers拡張も使えません)。困る人はステイです。
また、この設定を変更したときにDocker Desktopのサービスがいつまで経っても起動してくれないことが偶にあります。 その時はリセットして設定してみてください。なんとか頑張ってください。 ちなみに私は20分くらいかかりました。
使ってみよう
まずはWASMバイナリーを作ってみましょうか。
これはRustで書いた単純にhello world
を表示するだけのアプリケーションです。
fn main() { println!("Hello, world!"); }
コンパイルします。
$ rustup target add wasm32-wasi $ rustc hello.rs --target wasm32-wasm $ ls hello.rs hello.wasm*
WASMを実行するランタイムは色々あるのですが、今回はwasmtimeを使います。 インストール方法については公式サイト をどうぞ(上のコードと同じものがそのまま載っています)。
なお、macOSでHomebrewを使っている場合はwasmtimeのFormulae があります。
実行してみるとこのような感じです。
$ wasmtime hello.wasm Hello, world! $ file hello.wasm hello.wasm: WebAssembly (wasm) binary module version 0x1 (MVP)
作ったWASMバイナリーをDockerコンテナーで実行してみましょう。公式ドキュメント も参考にします。 このようなDockerfileを作成します。
# syntax=docker/dockerfile:1 FROM scratch COPY hello.wasm /hello.wasm ENTRYPOINT [ "/hello.wasm" ]
ベースイメージはこれを使ってみます。何も入っていないイメージです。
Dockerfileができたら、イメージをビルドしてみます。
docker buildx build --platform wasi/wasm -t ytooyama/hello-world .
ビルドを実行するとつぎのようなエラーが出るのですが(ここらへんはまだBetaなのでそのうち対応されると思います)、イメージはちゃんと作られています。
=> ERROR exporting to image 0.0s => => exporting layers 0.0s => => exporting manifest sha256:e54aa54d0d593a1b37fb6b8f493884fa2f2ddb0591a1451ad61c28cb311d0b9c 0.0s => => exporting config sha256:0ea51b5dd7448007256fc105ca689b49af09d7d161fb0ea0ec2da90cd76a03c6 0.0s => => exporting attestation manifest sha256:9f6bc8e96d73ecc176f524aa2f683781329e7ea8b91ee7ec358f4 0.0s => => exporting manifest list sha256:0d2e5cf178c5d13aff2c9021a56bfaa4733b772442c8b2bdafbcf4d45768 0.0s => => naming to docker.io/ytooyama/hello-world:latest 0.0s => => unpacking to docker.io/ytooyama/hello-world:latest 0.0s ------ > exporting to image: ------ ERROR: failed to solve: no match for platform in manifest sha256:0d2e5cf178c5d13aff2c9021a56bfaa4733b772442c8b2bdafbcf4d4576876de: not found View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/uig9chzy4n0l2t05x8hf7m8av
コマンドを実行してみましょう。イメージが見つかるはずです。
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE ytooyama/hello-world latest 0d2e5cf178c5 About a minute ago 516kB
作ったイメージはこちらにPushしておきました。
Docker Desktopが起動していない場合は予め起動しておきます。 端末を起動して、次のように実行してみましょう。
ランタイムはmacOSで実行したときと同じwastime
を使ってみます。
docker container run --rm \ --runtime=io.containerd.wasmtime.v1 \ --platform=wasi/wasm \ ytooyama/hello-world
実行すると、このような出力がされて終了します。
Hello, world!
これでmacOSでビルドして動いたアプリケーションをDockerで動かすことができました。
まとめ
クラウドネイティブなアプリケーションにとって、アプリケーション以外の部分、例えばライブラリーやLinuxを除くOS部分はある意味不要な部分です。アプリケーションさえ動いてくれれば良いわけですから。 WASMを使うとそんな理想に一歩近づきます。
Docker DesktopでWASMが使えるようになったのは第一歩だと思います。 Docker Desktop以外の様々な「プラットフォーム」でもWASMが使えるのが当たり前になれば、色々楽しくなりそうです。
WASMが当たり前に使われるようになれば、従来のコンテナーと異なりオーバーヘッドも少ないので、今よりシンプルで低スペックなコンピューターでアプリケーションを動かしたりとかもできそうですね。 家電でも車でもコンピューターが入っている時代ですので、色々変わってきそうな気がしています。 エッジコンピューティングでもWASMとか使われる様になるのかなあとか、想像すると楽しそうな気がします。