WASMコンテナはこれまでのコンテナを置き換えるのか

こんにちは、22新卒で入社したエンジニアのhashinoです。 この記事は Enigmo Advent Calendar 2022 の9日目の記事です。

背景

皆さん、普段コンテナを利用していますか?
エニグモでは、Kubernetesを活用していて、開発環境でもDockerを活用しています。

しかし、最近はWebAssemblyがコンテナを完全に置き換えるかもしれないという噂も耳にします。 既にKubernetesでは、kubelet API互換のKrustletが注目を集めています。kubeletは、ご存知の通りOCI準拠のコンテナを実行しますが、Krustletは、WebAssembly System InterfaceランタイムのWebAssemblyを実行するものです。Kubernetes上でPodの代わりにWebAssemblyを動作させることが可能になっています。 また、Fermyonでは、WebAssemblyマイクロサービスを構築するためのDeveloper ToolであるSpinを開発しております。
このような背景から、コンテナの代わりにWebAssemblyが利用される未来も想像ができるようになってきたところです。

そして、先々月末に大きなニュースが発表されました。
それが、DockerのWebAssemblyコンテナです。
https://www.docker.com/blog/docker-wasm-technical-preview/

この記事を読んだところ、Docker APIを使ってWASM Runtimeでの実行が可能になるということです。
さらには、WASM Imageなる概念もあり、これにより既存のDocker Imageと似たようなエコシステムやパイプラインの活用が期待できるということです。

DockerとWASMはどのように統合されたのか

多くの読者の方が気になっている点ですが、プレビューに書いてあった内容を簡単に私なりにまとめました。

  1. OCIアーティファクトとcontainerd-shimを活用している。
  2. OCI準拠のWebAssemblyランタイムであるWasmEdgeを採用し、そのためにcontainerd-wasm-shimを作成した。containerd-wasm-shimは、OCIアーティファクトからWASMモジュールを抽出し、WasmEdge Runtimeを使用して実行する。
  3. containerd-shimを使用できるようにするために、--runtime=io.containerd.wasmedge.v1フラグによって、WASM Runtimeを宣言できるようにした。

実際に私のMacBookのDocker DesktopでWASMコンテナを作成して実行してみました。 今回は、公式のサンプルを参考に進めました。

[デモ]実際にDocker DesktopでWASMを実行してみる

今回は、Go言語を使ってサンプルを作ります。 WASMへのコンパイルが容易なtinygoをインストールします。

brew tap tinygo-org/tools
brew install tinygo

そして、Hello WorldするだけのGoのプログラムを用意します。 本記事では、このコードをWASMバイナリにコンパイルして、それをOCIイメージとして利用可能であることを検証します。

package main

func main() {
    println("hello world")
}

では、まずWASMバイナリにコンパイルしましょう。

tinygo build -o wasm.wasm -target wasm ./main.go

このコマンドで、wasm.wasmというバイナリが出来上がります。

ここから、WASMコンテナ関連の部分に入っていきます。

先ほど作成したWASMバイナリをOCI互換のイメージにしていきます。 以下のように少し無理矢理ですが、Dockerfileを使って実現できます。

FROM scratch
COPY ./wasm.wasm /wasm.wasm
ENTRYPOINT [ "wasm.wasm" ]

ここで利用しているscratchというコンテナイメージは、Dockerコンテナを実現する上で最小限のもののみので構成された非常に軽量なコンテナイメージです。 今回は、Dockerイメージのエコシステムを活用するためにscratchの中にWASMモジュールを入れるように構成しています。

docker buildx build --platform wasi/wasm32 -t sample-wasm-container .

これでOCI互換のWASMイメージを作成できるはずなのですが、

------
 > exporting to image:
------
ERROR: failed to solve: operating system is not supported

このようなエラーに遭遇しました。(かなり詰まりました汗)

Docker DesktopのContainerdのイメージストア機能はデフォルトではOFFのようなので、ONにする必要があります。

以下のリンクの手順通りに進めることで解決しました。 https://docs.docker.com/desktop/containerd/

もう一度以下のコマンドを実行すると成功します。

docker buildx build --platform wasi/wasm32 -t sample-wasm-container .

では、出来上がったイメージを見てみましょう。

➜ docker image ls
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
sample-wasm-container   0.1       1711f20d1ef5   4 minutes ago   128kB

➜ docker image inspect sample-wasm-container | grep -A 3 "Architecture"
        "Architecture": "wasm32",
        "Os": "wasi",
        "Size": 127948,
        "VirtualSize": 127948,

wasm32というArchitectureのイメージができていることが確認できます。

では、ここからこのイメージをDocker Hubに登録していきます。

docker image tag sample-wasm-container mikiko/sample-wasm-container:1.0
docker image push hashino/sample-wasm-container:1.0

ところが、以下のようなエラーが出ました。

server message: insufficient_scope: authorization failed

以下のコマンドで再度dockerにログインすることで解決できました。

docker login

Docker HubのWebUIからもDockerイメージが保存されていることが確認できます。

では、実際にDocker Hubに保存したWASMイメージを実行してみましょう。

docker container run --rm --name= \
--runtime=io.containerd.wasmedge.v1 \
--platform=wasi/wasm32 \
mikiko/hello-wasm-container:0.1

hello world

うまく実行することができました!

まとめ

本記事では、先々月に発表されたDocker WASMコンテナを実際に実行してみるところまで進めました。

Dockerが公開したWASMコンテナを検証してみました。

これまで通りのコンテナレジストリを活用したビルドやデプロイに関するエコシステムを活かして、WASMを導入できることが分かりました。

ぜひ、皆さんもご検証ください!!

参考文献


株式会社エニグモ すべての求人一覧

hrmos.co