CL LAB

HOME > CL LAB > Docker 24リリース! containerdイメージストア統合の実験的サポートでWASMを動かそう #docker #containerd #stargz #webassembly #wasm #wasi

Docker 24リリース! containerdイメージストア統合の実験的サポートでWASMを動かそう #docker #containerd #stargz #webassembly #wasm #wasi

 ★ 11

2023年5月17日に Docker 24.0.0 が正式リリースされ、引き続き 2023年5月29日にバグフィックスリリースである v24.0.1 がリリースされました。

「あれ、まだ2024年じゃないけど?」と思われた方もいるかもしれません。Docker 23.0.0から、YY.MM.zz という年月バージョン番号ポリシーから セマンティックバージョニング に変更されているため、このような大きな数字になっています。

v24.0.0 での目玉機能は、containerdイメージストア統合の実験的サポート と思われます。この実験的機能を有効にすることでイメージの格納・プッシュ・プルに、Docker独自のイメージストアではなく、containerdのイメージストアを利用できるようになります。以前24ベータ版で試用してみましたが、本稿では v24.0.1 正式版でcontainerdイメージストア統合の実験的サポートを有効にしてみます。

注意: 本稿の内容は実験であり、本番環境では利用できません。また、開発中のソフトウェアを多数利用しているため、今後動作が変更される可能性があります。

事前準備

Virtualbox に RockyLinux 9 を準備して、こちらで実験環境を作っていきます。
Docker 24.0.1 は正式リリースされたので 通常のインストール手順 でインストール可能です。テスト版レポジトリの設定など特殊な手順は必要ありません。

[vagrant@node1 ~]$ docker version
Client: Docker Engine - Community
 Version:           24.0.1
 API version:       1.43
 Go version:        go1.20.4
 Git commit:        6802122
 Built:             Fri May 19 18:07:44 2023
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          24.0.1
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.4
  Git commit:       463850e
  Built:            Fri May 19 18:06:05 2023
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.21
  GitCommit:        3dce8eb055cbb6872793272b4f20ed16117344f8
 runc:
  Version:          1.1.7
  GitCommit:        v1.1.7-0-g860f061
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
[vagrant@node1 ~]$ 

インストール直後はDocker独自のイメージストアを利用しています。

[vagrant@node1 ~]$ docker system info
(略)
Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
 Server Version: 24.0.1
 Storage Driver: overlay2
  Backing Filesystem: xfs
(略)

containerdイメージストアへの切り替え

では、Docker独自のイメージストアから、containerdのイメージストアに切り替えてみましょう。24ベータ版 と同様に、containerd/stargz-snapshotter の手順に従います。

Dockerデーモンの設定を変更します。

[vagrant@node1 ~]$ cat | sudo tee -a /etc/docker/daemon.json
{
  "features": {
    "containerd-snapshotter": true
  },
  "storage-driver": "stargz"
}
[vagrant@node1 ~]$

containerdの設定を変更します。

[vagrant@node1 ~]$ sudo cp -a /etc/containerd/config.toml config.toml.orig
[vagrant@node1 ~]$ cat | sudo tee /etc/containerd/config.toml
version = 2

# Plug stargz snapshotter into containerd
[proxy_plugins]
  [proxy_plugins.stargz]
    type = "snapshot"
    address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock"
[vagrant@node1 ~]$ 

fuseをインストールします。ここではインストール済みです。

[vagrant@node1 ~]$ sudo yum install -y fuse
Last metadata expiration check: 0:11:06 ago on Thu 25 May 2023 06:40:57 AM UTC.
Package fuse-2.9.9-15.el9.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!
[vagrant@node1 ~]$ sudo modprobe fuse
[vagrant@node1 ~]$

stargz-snapshotterの本稿執筆時点最新のバージョンv0.14.3バイナリとsystemdユニットファイルをインストールします。

[vagrant@node1 ~]$ sudo tar -C /usr/local/bin/ -xvf stargz-snapshotter-v0.14.3-linux-amd64.tar.gz
containerd-stargz-grpc
ctr-remote
stargz-store
[vagrant@node1 ~]$ sudo curl -L https://raw.githubusercontent.com/containerd/stargz-snapshotter/v0.14.3/script/config/etc/systemd/system/stargz-snapshotter.service  -o /etc/systemd/system/stargz-snapshotter.service
[vagrant@node1 ~]$ sudo chcon system_u:object_r:systemd_unit_file_t:s0 /etc/systemd/system/stargz-snapshotter.service
[vagrant@node1 ~]$ sudo systemctl enable --now stargz-snapshotter
Created symlink /etc/systemd/system/multi-user.target.wants/stargz-snapshotter.service → /etc/systemd/system/stargz-snapshotter.service.
[vagrant@node1 ~]$

containerdとDockerデーモンを再起動します。

[vagrant@node1 ~]$ sudo systemctl restart containerd
[vagrant@node1 ~]$ sudo systemctl restart docker
[vagrant@node1 ~]$ 

イメージストアが切り替わったかどうか確認しましょう。

[vagrant@node1 ~]$ docker system info
(略)
 Server Version: 24.0.1
 Storage Driver: stargz
  driver-type: io.containerd.snapshotter.v1
 Logging Driver: json-file
(略)

ストレージドライバが stargz 、ドライバタイプが io.containerd.snapshotter.v1 になっていれば切り替え完了です。

イメージストアの確認

実際にイメージをプルして確認してみましょう。

まず、Dockerとcontainerdのどちらでもイメージが存在しないことを確認します。

[vagrant@node1 ~]$ docker image ls -a
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE
[vagrant@node1 ~]$ sudo ctr --namespace moby image ls
REF TYPE DIGEST SIZE PLATFORMS LABELS 
[vagrant@node1 ~]$

Dockerで nginx:1.22 イメージをプルしてみます。

[vagrant@node1 ~]$ docker image pull nginx:1.22
fc5f5fb75747: Download complete 
908106471267: Download complete 
0f8498f13f3a: Download complete 
2a9f38700bb5: Download complete 
ef2fc869b944: Download complete 
ac713a9ef2cc: Download complete 
fd071922d543: Download complete 
f1f26f570256: Download complete 
fd03b214f774: Download complete 
docker.io/library/nginx:1.22
[vagrant@node1 ~]$

Dockerとcontainerdの両方でイメージを確認してみましょう。

[vagrant@node1 ~]$ docker image ls 
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
nginx        1.22      fc5f5fb75747   18 seconds ago   211MB
[vagrant@node1 ~]$ sudo ctr --namespace moby image ls
REF                          TYPE                                                      DIGEST                                                                  SIZE     PLATFORMS                                                                                               LABELS 
docker.io/library/nginx:1.22 application/vnd.docker.distribution.manifest.list.v2+json sha256:fc5f5fb7574755c306aaf88456ebfbe0b006420a184d52b923d2f0197108f6b7 54.4 MiB linux/386,linux/amd64,linux/arm/v5,linux/arm/v7,linux/arm64/v8,linux/mips64le,linux/ppc64le,linux/s390x -      
[vagrant@node1 ~]$

Dockerでプルした nginx:1.22 イメージが、containerdのイメージストアでも見えているので、切り替えが正常に完了しています。

DockerでWASM/WASIを動かす設定

では、DockerでWASI (WebAssembly System Interface)を動かせるように設定しましょう。ここでは WasmEdgerunwasi を使います。過去の手順は「DockerでWASMを動かそう」をご覧ください。

まず、WasmEdgeをインストールします。本稿執筆時点のWasmEdge最新版 0.12.1 では runwasi との組み合わせがうまく動かないので、少しバージョンの古い 0.11.2 をインストールします。詳細は過去記事「KubernetesでWASMを動かそう」をご覧ください。

[vagrant@node1 ~]$ curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash -s -- -v 0.11.2
(略)
WasmEdge Successfully installed
Run:
source /home/vagrant/.bashrc
[vagrant@node1 ~]$ sudo cp -a .wasmedge/lib/libwasmedge.so* /usr/local/lib/
[vagrant@node1 ~]$ sudo -E sh -c 'echo "/usr/local/lib" > /etc/ld.so.conf.d/libwasmedge.conf'
[vagrant@node1 ~]$ sudo ldconfig
[vagrant@node1 ~]$ ldd ./.wasmedge/bin/wasmedge
	linux-vdso.so.1 (0x00007ffe6c988000)
	libwasmedge.so.0 => /usr/local/lib/libwasmedge.so.0 (0x00007f3becacb000)
	libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f3bec8a4000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f3bec7c9000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f3bec7ae000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f3bec7a9000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f3bec5a0000)
	librt.so.1 => /lib64/librt.so.1 (0x00007f3bec599000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f3bec594000)
	libz.so.1 => /lib64/libz.so.1 (0x00007f3bec57a000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f3bef75b000)
[vagrant@node1 ~]$ ./.wasmedge/bin/wasmedge --version
./.wasmedge/bin/wasmedge version 0.11.2
[vagrant@node1 ~]$

runwasi をインストールします。本稿執筆時点では runwasi のビルド済みバイナリが配布されていないため(参照tar.gz files included in releases are empty)、過去記事「DockerでWASMを動かそう」でビルドしたバイナリを利用します。ビルド方法の詳細はそちらをご覧ください。

$ git clone https://github.com/containerd/runwasi
$ cd runwasi
$ git checkout containerd-shim-wasm/v0.1.2
$ docker image build -t runwasi .
(略)
$ docker image save runwasi | tar xf -
$ tar xvf XXXXX/layer.tar
containerd-shim-wasmedge-v1
containerd-shim-wasmedged-v1
containerd-shim-wasmtime-v1
containerd-shim-wasmtimed-v1
containerd-wasmedged
containerd-wasmtimed
wasi-demo-app
$
[vagrant@node1 ~]$ sudo cp containerd-* /usr/bin/
[vagrant@node1 ~]$ sudo ldd /usr/bin/containerd-shim-wasmedge-v1 
	linux-vdso.so.1 (0x00007ffe065f7000)
	libwasmedge.so.0 => /usr/local/lib/libwasmedge.so.0 (0x00007f47dda1e000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f47dd815000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f47e0a47000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f47dd7fa000)
	librt.so.1 => /lib64/librt.so.1 (0x00007f47dd7f5000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f47dd7f0000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f47dd715000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f47dd70e000)
	libz.so.1 => /lib64/libz.so.1 (0x00007f47dd6f4000)
	libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f47dd4cd000)
[vagrant@node1 ~]$ 

これでDockerでWASM/WASIを動かす準備ができました。

runwasiのテスト

では動作テストとして、Running a Wasm application with docker run のサンプル WASM アプリケーションを実行してみましょう。

[vagrant@node1 ~]$ docker container run -dp 8080:8080 \
  --name=wasm-example \
  --runtime=io.containerd.wasmedge.v1 \
  --platform=wasi/wasm32 \
  michaelirwin244/wasm-example
Unable to find image 'michaelirwin244/wasm-example:latest' locally
2a58923a21cb: Download complete 
130eeaf02640: Download complete 
e049f00c5289: Download complete 
fb4e36b5f8158f12717a38d626488b5ef01fcca89aa2563b4be0634a9b3aec1c
[vagrant@node1 ~]$ curl localhost:8080 ; echo
Hello world from Rust running with Wasm! Send POST data to /echo to have it echoed back to you
[vagrant@node1 ~]$ curl -d 'Hello, world!' localhost:8080/echo ; echo 
Hello, world!
[vagrant@node1 ~]$ docker container rm -f wasm-example 
wasm-example
[vagrant@node1 ~]$ 

問題なくサンプル WASM アプリを実行することができました。動作も問題ないようです。

WASMのDockerイメージの作成

前項では準備済みのWASMのDockerイメージを使いましたが、自作もしてみましょう。

まずはWASMバイナリを作成する必要があります。過去記事「RubyでWebAssemblyを試してみよう」で作成した hello.wasm をDockerイメージにしてみましょう。WASMバイナリの詳細な作成手順はそちらをご覧ください。

% mkdir src
% echo 'puts "Hello, world!"' > src/hello.rb
% export WASI_VFS_VERSION=0.2.0
% curl -LO "https://github.com/kateinoigakukun/wasi-vfs/releases/download/v${WASI_VFS_VERSION}/wasi-vfs-cli-x86_64-unknown-linux-gnu.zip"
% unzip wasi-vfs-cli-x86_64-unknown-linux-gnu.zip
% curl -LO https://github.com/ruby/ruby.wasm/releases/latest/download/ruby-3_2-wasm32-unknown-wasi-full.tar.gz
% tar xf ruby-3_2-wasm32-unknown-wasi-full.tar.gz
% curl -LO https://github.com/bytecodealliance/wasmtime/releases/download/v7.0.0/wasmtime-v7.0.0-x86_64-linux.tar.xz
% tar xf wasmtime-v7.0.0-x86_64-linux.tar.xz
% ./wasi-vfs pack ./3_2-wasm32-unknown-wasi-full/usr/local/bin/ruby --mapdir /src::./src --mapdir /usr::./3_2-wasm32-unknown-wasi-full/usr -o hello.wasm
% file ./hello.wasm
./hello.wasm: WebAssembly (wasm) binary module version 0x1 (MVP)
%

次にこの hello.wasm をDockerイメージとします。過去記事「DockerでWASMを動かそう」の手順は、実は間違っていました。あらためて本稿でWASMをDockerイメージとする手順を見ていきます。

まず新しくディレクトリを作り、その中に hello.wasm と次のDockerfileを配置します。

FROM scratch
COPY hello.wasm /hello.wasm
ENTRYPOINT [ "hello.wasm", "/src/hello.rb" ]

ここでDockerfileをビルド…する前に準備が必要です。過去記事「DockerでWASMを動かそう」では、この準備が抜けていました。linux/amd64 で wasm/wasi32 をビルドしようとしているので、マルチプラットフォームイメージのビルド設定が必要だったようです。

では、マルチプラットフォームイメージのビルド準備をしていきましょう。現在のビルダーを一覧表示します。

[vagrant@node1 hello]$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS  BUILDKIT PLATFORMS
default * docker                           
  default default         running v0.11.6  linux/amd64, linux/amd64/v2
[vagrant@node1 hello]$

wasm/wasi32 をビルドするためのビルダーを作成します。ここでは wasmbuilder という名前をつけています。

[vagrant@node1 hello]$ docker buildx create --name wasmbuilder --driver docker-container --bootstrap
[+] Building 15.9s (1/1) FINISHED                                               
 => [internal] booting buildkit                                           15.9s
 => => pulling image moby/buildkit:buildx-stable-1                        14.5s
 => => creating container buildx_buildkit_wasmbuilder0                     1.3s
wasmbuilder
[vagrant@node1 hello]$

wasmbuilder を作成できたことを確認します。

[vagrant@node1 hello]$ docker buildx ls
NAME/NODE      DRIVER/ENDPOINT             STATUS  BUILDKIT PLATFORMS
wasmbuilder    docker-container                             
  wasmbuilder0 unix:///var/run/docker.sock running v0.11.6  linux/amd64, linux/amd64/v2, linux/386
default *      docker                                       
  default      default                     running v0.11.6  linux/amd64, linux/amd64/v2
[vagrant@node1 hello]$ docker buildx inspect wasmbuilder
Name:          wasmbuilder
Driver:        docker-container
Last Activity: 2023-05-25 07:36:48 +0000 UTC

Nodes:
Name:      wasmbuilder0
Endpoint:  unix:///var/run/docker.sock
Status:    running
Buildkit:  v0.11.6
Platforms: linux/amd64, linux/amd64/v2, linux/386
[vagrant@node1 hello]$ docker ps
CONTAINER ID   IMAGE                           COMMAND       CREATED         STATUS         PORTS     NAMES
c8556b04e6cd   moby/buildkit:buildx-stable-1   "buildkitd"   2 minutes ago   Up 2 minutes             buildx_buildkit_wasmbuilder0
[vagrant@node1 hello]$ 

PLATFORMSに wasm/wasi32 は載っていませんが、これでいいようです。wasmbuilder をビルダーとして使用するように切り替えます。

[vagrant@node1 hello]$ docker buildx use wasmbuilder
[vagrant@node1 hello]$

では、Dockerイメージをビルドしてみましょう。ここでビルドコマンドに「--load」というオプションを付与する必要があります。

[vagrant@node1 hello]$ docker buildx build --platform wasi/wasm32 --load -t daihiguchi/hellowasm .
[+] Building 6.0s (6/6) FINISHED                                                
 => [internal] load build definition from Dockerfile                       0.0s
 => => transferring dockerfile: 182B                                       0.0s
 => [internal] load .dockerignore                                          0.0s
 => => transferring context: 2B                                            0.0s
 => [internal] load build context                                          0.0s
 => => transferring context: 93B                                           0.0s
 => CACHED [1/1] COPY hello.wasm /hello.wasm                               0.0s
 => exporting to docker image format                                       5.9s
 => => exporting layers                                                    3.8s
 => => exporting manifest sha256:15f74db4faf0675e838ddd3531b871bd34243d78  0.0s
 => => exporting config sha256:4bef0b7a7115ad6135e46accc5a28bda692850efde  0.0s
 => => sending tarball                                                     2.1s
 => importing to docker                                                    0.0s
[vagrant@node1 hello]$ 

ビルドに成功しました! 別途ビルダーを作成していない過去記事「DockerでWASMを動かそう」では、

 => [1/1] COPY hello.wasm /hello.wasm                                      0.3s
 => ERROR exporting to image                                               4.5s
ERROR exporting to image
(略)
------
 > exporting to image:
------
ERROR: failed to solve: no match for platform in manifest sha256:6f6933e0f8dc102e51c1c7036060a20d325efce8c69dce85628aecae5ce8ebd5: not found

というエラーになっていましたが、正常に export できました。

[vagrant@node1 hello]$ docker image ls
REPOSITORY                     TAG               IMAGE ID       CREATED          SIZE
daihiguchi/hellowasm           latest            15f74db4faf0   21 seconds ago   74MB
nginx                          1.22              fc5f5fb75747   36 minutes ago   211MB
michaelirwin244/wasm-example   latest            2a58923a21cb   28 minutes ago   6.31MB
moby/buildkit                  buildx-stable-1   d6fa89830c26   6 minutes ago    246MB
[vagrant@node1 hello]$ sudo ctr --namespace moby image ls
REF                                           TYPE                                                      DIGEST                                                                  SIZE     PLATFORMS                                                                                               LABELS 
docker.io/daihiguchi/hellowasm:latest         application/vnd.docker.distribution.manifest.v2+json      sha256:15f74db4faf0675e838ddd3531b871bd34243d78edc628d7afc6211726c2f65c 17.2 MiB wasi/wasm32                                                                                             -      
docker.io/library/nginx:1.22                  application/vnd.docker.distribution.manifest.list.v2+json sha256:fc5f5fb7574755c306aaf88456ebfbe0b006420a184d52b923d2f0197108f6b7 54.4 MiB linux/386,linux/amd64,linux/arm/v5,linux/arm/v7,linux/arm64/v8,linux/mips64le,linux/ppc64le,linux/s390x -      
docker.io/michaelirwin244/wasm-example:latest application/vnd.docker.distribution.manifest.v2+json      sha256:2a58923a21cb3d45bc4a254120356c15869519603563609eacd8a39b54869b00 1.5 MiB  wasi/wasm32                                                                                             -      
docker.io/moby/buildkit:buildx-stable-1       application/vnd.oci.image.index.v1+json                   sha256:d6fa89830c26919acba23c5cafa09df0c3ec1fbde20bb2a15ff349e0795241f4 72.8 MiB linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/riscv64,linux/s390x,unknown/unknown            -      
[vagrant@node1 hello]$ 

dockerコマンド、ctrコマンドの両方から作成できたDockerイメージが問題なく見えています。

作成したWASMのDockerイメージを使ってコンテナを実行

早速Dockerコンテナとして実行してみましょう。

[vagrant@node1 hello]$ docker container run --rm --runtime=io.containerd.wasmedge.v1 --platform=wasi/wasm32 daihiguchi/hellowasm
Hello, world!
[vagrant@node1 hello]$ 

無事、想定通りに動作しました!

まとめ

本稿では正式リリースされたDocker 24.0.1を使って、実験的サポートであるcontainerdイメージストア統合を有効化し、さらにWASM/WASIのDockerイメージの作成とコンテナの実行を行ってみました。
実験的サポートとはいえcontainerdイメージストア統合がDockerの正式リリースに組み込まれたことで、この動きは今後加速してくと考えられます。それに合わせてDockerにおけるWASM/WASIの実験や活用についても広がっていくことが期待されます。
クリエーションラインでは引き続き WebAssmbly と Docker について調査していきたいと思います。

CL LAB Mail Magazine

CL LABの情報を逃さずチェックしよう!

メールアドレスを登録すると記事が投稿されるとメールで通知します。

メールアドレス: 登録

※登録後メールに記載しているリンクをクリックして認証してください。

Related post

Neo4j[ホワイトペーパー]CCPA