[WebAssembly (Wasm)] Docker + Wasm(测试版):使用 Docker 和 WasmEdege 运行 WebAssembly (Wasm) 镜像

Docker + Wasm(测试版):使用 Docker 和 WasmEdege 运行 WebAssembly (Wasm) 镜像

WebAssembly,通常简称为 Wasm,是一种相对较新的技术,它允许你编译用 40 多种语言(包括 Rust、C、C++、JavaScript 和 Golang)编写的应用程序代码,并在沙盒环境中运行它。

最初的用例主要是在 Web 浏览器中运行本地代码,例如 Figma、AutoCAD 和 Photoshop。

但是由于 WebAssembly 系统接口(WASI)的存在,Wasm 正在迅速向浏览器之外扩展,Vercel、Fastly、Shopify 和 Cloudflare 等公司支持使用 Wasm 在边缘运行代码,而 Fermyon 正在构建一个平台,以在云上运行 Wasm 微服务。

在 KubeCon NA 2022 大会的云原生 Wasm 活动日中,Docker 宣布与 CNCF Wasm 运行时项目 WasmEdge 合作推出 Docker + Wasm 技术预览。只需一个命令 docker rundocker compose up,Docker 开发人员就可以立即构建、分享和运行一个完整的 Wasm 应用程序。

Wasm(WebAssembly 的缩写)是您目前在 Docker 中使用的 Linux 和 Windows 容器的一种快速、轻便的替代方案(有 一些折衷)。

此页面提供有关在 Docker 中与 Linux 容器一起运行 Wasm 应用程序的新功能的信息。

测试版

提醒
Docker + Wasm 功能目前处于 Beta阶段。我们建议您不要在生产环境中使用此功能,因为此功能可能会更改或从未来版本中删除。

首先,我们需要提醒你,由于这是一个技术预览,事情可能会很快发生变化,但这是它目前的工作方式。

  • 我们正在利用我们最近的工作,将镜像管理迁移到 containerd,因为它提供了使用与 OCI 兼容的工件和 containerd shims 的能力。

  • 我们与 WasmEdge 合作创建了一个 containerd shim。此 shim 从 OCI 工件中提取 Wasm 模块并使用 WasmEdge 运行时运行它。

  • 我们添加了对声明 Wasm 运行时的支持,这将允许使用这个新的 shim。

docker-containerd-wasm-diagram

开启 Docker + Wasm 集成

要使用 Docker + Wasm 集成,开发人员必须打开 containerd 镜像存储 - https://docs.docker.com/desktop/containerd/功能。

重要的
Docker + Wasm 集成需要 containerd 镜像存储 - https://docs.docker.com/desktop/containerd/功能。如果您尚未使用 containerd 镜像存储,则将无法访问预先存在的镜像和容器。

  • 默认情况下,containerd 镜像存储测试版功能处于关闭状态。

  • 要开始使用该功能:

    1. 导航到 Preferences

    2. 选择 Features in development 功能选项卡。

    3. 选择 Beta features 选项卡。

    4. Use containerd for pulling and storing images 旁边,选中 复选框

    5. 点击 Apply & restart 重启 Docker Desktop。

要关闭此功能,请清除使用 containerd 提取和存储镜像 复选框。

containerd_feature_activation

使用示例

运行 Wasm 应用程序 docker run

以下 docker run 命令在您的系统上启动一个 Wasm 容器:

1
2
3
4
5
$ docker run -dp 8080:8080 \
--name=wasm-example \
--runtime=io.containerd.wasmedge.v1 \
--platform=wasi/wasm32 \
michaelirwin244/wasm-example

收到错误消息?前往故障排除部分 - https://docs.docker.com/desktop/wasm/#troubleshooting 寻求帮助。

请注意此命令中使用的--runtime--platform标志:

  • --runtime=io.containerd.wasmedge.v1:通知 Docker 引擎你想使用 Wasm containerd shim 而不是标准的 Linux 容器运行时

  • --platform=wasi/wasm32:指定要使用的镜像的体系结构。通过利用 Wasm 架构,您无需为不同的机器架构构建单独的镜像。Wasm 运行时负责将 Wasm 二进制文件转换为机器指令的最后一步。

该示例应用是一个简单的 Web 服务器,它会显示 Hello world! 并将数据回显给我们,为了验证它是否正常工作,让我们首先查看日志。

1
2
3
4
[2022-12-10 14:29:17.851] [info] loading failed: malformed section id, Code: 0x25
[2022-12-10 14:29:17.851] [info] AOT arch type unmatched.
[2022-12-10 14:29:17.851] [info] Load AOT section failed. Use interpreter mode instead.
Server is now running

我们可以通过打开 http://localhost:8080 或使用 curl 来获取 Hello world 消息。

1
2
$ curl http://localhost:8080
Hello world from Rust running with Wasm! Send POST data to /echo to have it echoed back to you

将数据发送到 echo 端点,我们可以使用 curl 命令:

1
2
$ curl localhost:8080/echo -d '{"message":"Hi there"}' -H "Content-type: application/json"
{"message":"Hi there"}

要删除应用程序,可以像执行任何其他 Docker 服务一样删除它:

1
docker rm -f wasm-example

使用 Docker Compose 运行 Wasm 应用程序

可以使用以下 Docker Compose 文件运行相同的应用程序:

1
2
3
4
5
6
7
services:
app:
image: michaelirwin244/wasm-example
platform: wasi/wasm32
runtime: io.containerd.wasmedge.v1
ports:
- 8080:8080

使用普通的 Docker Compose 命令启动应用程序:

1
$ docker compose up

使用 Wasm 运行多服务应用程序

网络的工作方式与您对 Linux 容器的预期相同,使您可以灵活地将 Wasm 应用程序与其他容器化工作负载(例如数据库)组合在单个应用程序堆栈中。

在以下示例中,Wasm 应用程序利用在容器中运行的 MariaDB 数据库。

  1. 克隆存储库。
1
2
3
4
5
6
7
8
$ git clone https://github.com/second-state/microservice-rust-mysql.git
Cloning into 'microservice-rust-mysql'...
remote: Enumerating objects: 75, done.
remote: Counting objects: 100% (75/75), done.
remote: Compressing objects: 100% (42/42), done.
remote: Total 75 (delta 29), reused 48 (delta 14), pack-reused 0
Receiving objects: 100% (75/75), 19.09 KiB | 1.74 MiB/s, done.
Resolving deltas: 100% (29/29), done.
  1. 导航到克隆的项目并使用 Docker Compose 启动项目。
1
2
3
4
5
6
7
8
$ cd microservice-rust-mysql
$ docker compose up
[+] Running 0/1
⠿ server Warning 0.4s
[+] Building 4.8s (13/15)
...
microservice-rust-mysql-db-1 | 2022-10-19 19:54:45 0 [Note] mariadbd: ready for connections.
microservice-rust-mysql-db-1 | Version: '10.9.3-MariaDB-1:10.9.3+maria~ubu2204' socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution

如果您docker image ls从另一个终端窗口运行,您可以在镜像存储中看到 Wasm 镜像。

1
2
3
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
server latest 2c798ddecfa1 2 minutes ago 3MB

检查镜像显示镜像有一个wasi/wasm32平台,操作系统和架构的组合:

1
2
3
4
5
$ docker image inspect server | grep -A 3 "Architecture"
"Architecture": "wasm32",
"Os": "wasi",
"Size": 3001146,
"VirtualSize": 3001146,
  1. 在浏览器中打开 URL http://localhost:8090 并创建一些示例订单。所有这些都在与 Wasm 服务器进行交互。

  2. Ctrl+C完成后,通过点击启动应用程序的终端来拆除所有内容。

构建和推送 Wasm 模块

  1. 创建一个 Dockerfile 来构建您的 Wasm 应用程序。具体如何执行此操作因您使用的编程语言而异。

  2. 在您的一个单独阶段中Dockerfile,提取模块并将其设置为ENTRYPOINT.

1
2
3
4
5
6
7
# syntax=docker/dockerfile:1

FROM scratch

COPY --from=build /build/hello_world.wasm /hello_world.wasm

ENTRYPOINT [ "hello_world.wasm" ]
  1. 构建并推送指定wasi/wasm32架构的镜像。Buildx 使这很容易在一个命令中完成。
1
2
3
4
5
6
7
8
9
$ docker buildx build --platform wasi/wasm32 -t username/hello-world .
...
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => exporting manifest sha256:2ca02b5be86607511da8dc688234a5a00ab4d58294ab9f6beaba48ab3ba8de56 0.0s
=> => exporting config sha256:a45b465c3b6760a1a9fd2eda9112bc7e3169c9722bf9e77cf8c20b37295f954b 0.0s
=> => naming to docker.io/username/hello-world:latest 0.0s
=> => unpacking to docker.io/username/hello-world:latest 0.0s
$ docker push username/hello-world

故障排除

本节包含有关如何解决常见问题的说明。

指定的未知运行时

如果您在选择使用 containerd 镜像存储之前尝试运行 Wasm 容器,则会显示类似于以下内容的错误:

1
docker: Error response from daemon: Unknown runtime specified io.containerd.wasmedge.v1.

在 Docker Desktop 设置中打开 containerd 功能 - https://docs.docker.com/desktop/containerd/#enabling-the-containerd-image-store-feature ,然后重试。

无法启动 shim:无法解析运行时路径

如果您使用不支持运行 Wasm 容器的旧版本 Docker Desktop,您将看到类似于以下内容的错误消息:

1
docker: Error response from daemon: failed to start shim: failed to resolve runtime path: runtime "io.containerd.wasmedge.v1" binary not installed "containerd-shim-wasmedge-v1": file does not exist: unknown.

将您的 Docker Desktop 更新到最新版本,然后重试。

已知问题

Docker Compose 在中断时可能不会干净地退出

解决方法:通过向进程发送 SIGKILL (killall -9 docker-compose)来清理进程 docker-compose

server message: insufficient_scope: authorization failed即使在使用 Docker Desktop 登录后, 推送到 Hub 也可能会出现错误 提示

解决方法:docker login 在 CLI 中运行

反馈

感谢您尝试新的 Docker + Wasm 集成。通过公共路线图项目 - https://github.com/docker/roadmap/issues/426上的问题跟踪器提供反馈或报告您可能发现的任何错误。

参考链接

[1] Docker + Wasm (Beta) | Docker Documentation - https://docs.docker.com/desktop/wasm/

[2] Introducing the Docker+Wasm Technical Preview | Docker - https://www.docker.com/blog/docker-wasm-technical-preview/

[3] Docker: Accelerated, Containerized Application Development - https://www.docker.com/

[4] Overview | Docker Documentation - https://docs.docker.com/compose/

[5] WebAssembly - https://webassembly.org/

[6] WasmEdge - https://wasmedge.org/

[7] containerd – An industry-standard container runtime with an emphasis on simplicity, robustness and portability - https://containerd.io/