本文为译文,原文见:https://nigelpoulton.com/getting-started-with-docker-and-wasm/
轻松体验 Docker 和 Wasm ——编写一个应用,将其编译为 Wasm,将其打包为 OCI 镜像,将之存储在 Docker Hub 中,使用 Docker 运行它......
Docker 最近发布了支持 WebAssembly 的 Docker Desktop 技术预览版。 他们还宣布了 Docker Hub 对 WebAssembly artifacts 的支持。
因为我觉得 WebAssembly 非常有意思,所以我想我应该把它们都试一试,然后写一篇文章来帮助其他任何想亲身体验 Docker 和 Wasm 的人。
WebAssembly (又称 Wasm) 创建非常小、非常快的二进制文件,这些二进制文件在任何地方的安全沙箱中执行,只要有一个 WebAssembly Runtime。说实话……它们比容器更小、更快、更安全,而且更加跨平台—— 这话是我说的,我承认我是容器的超级粉丝。
关于体积大小的例子,Michael Yuan 最近分享了有着完整的 HTTP 服务器 + MySQL 客户端“app服务器”,只有 2MB!其他人也分享了 Size 更小的 Example。
无论如何,WebAssembly 正成为云原生领域的一件大事,而 Docker 也想在此有一席之地。
我将一步一步带领你编写一个 hello world Wasm 应用,将其打包为 OCI 镜像以及推送到 Docker Hub,并使用 Docker 运行它。如果你想跟我一起做,你需要做下面两个准备,但如果你只是想阅读,那也没关系。
可以从此页面上的链接安装 Docker Desktop 技术预览版,并从这里安装 Rust。Docker Desktop 和 Rust 安装后,我们将完成以下步骤:
下文的所有任务都将使用命令行执行。 你会需要 Docker Desktop 和 Rust 。
运行下面的 rustup
命令,安装 wasm32-wasi target。这样 Rust 就可以将源代码编译成 Wasm 二进制文件。
rustup target add wasm32-wasi
如果你运行 rustup target list
,发现 wasm32-wasi (installed) 出现在列表里, Rust 就配置好了,你就可以创建这个app了。
运行以下命令来构建一个简单的 Rust app。 它将创建一个简单的 Hello World 应用 hello-docker/src/main.rs
。
cargo new hello-docker
检查 hello-docker/src/main.rs
文件并更改打印到屏幕上的文字。 我更改为打印“Hello, Docker Hub!” 了。如下。
fn main() {
println!("Hello, Docker Hub!");
}
此时,Rust app 已编写好,并可以编译为 Wasm 二进制文件了。
运行以下 cargo
命令将 Rust app 为 wasm32-wasi 二进制文件。 这将创建一个 Wasm 字节码二进制文件,它可以在任何有 WebAssembly 运行时的系统上运行。
cargo
命令作为 Rust 的一部分已经安装。 它还知道在哪里可以找到源代码以及如何将其编译为 Wasm 二进制文件。
cargo build --target wasm32-wasi --release
该命令将 hello-docker.wasm
Wasm 二进制文件输出到 hello-docker/target/wasm32-wasi/release
文件夹中。
我们将在接下来的步骤中借助 Docker 执行它。 然而,在此之前,我们会将其构建到 OCI 镜像中,以便它可以存储在 Docker Hub 中并由 Docker 执行。
Docker 可以将 Wasm 模块打包到 OCI 镜像中( Docker 镜像的别名)。
现在执行此操作的方式感觉有点过时,我希望将来会有所改变。 但是,你从一个临时基础镜像开始,复制 Wasm 模块,并将程序设置为作为 Wasm 二进制文件执行。
以下的 Dockerfile
对此进行了描述。 在你的当前目录中创建它(你应该在你的 hello-docker
目录中)。
FROM scratch
COPY ./target/wasm32-wasi/release/hello-docker.wasm /hello-docker.wasm
ENTRYPOINT [ "hello-docker.wasm" ]
创建 Dockerfile 后,运行以下命令来构建镜像。 该命令假定你与 Dockerfile 位于同一目录中。
docker buildx build --platform wasi/wasm32 -t docker-wasm:0.1 .
--platform wasi/wasm32
flag 将镜像的目标操作系统设置为 wasi 并将目标架构设置为 wasm32。 -t docker-wasm:0.1
标记/命名镜像“docker-wasm:0.1”,最后的句点告诉 Docker 使用当前目录中的 Dockerfile。
运行以下命令以验证新镜像是否存在。
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-wasm 0.1 6b43e0bdf164 2 mins 501kB
此时 Wasm app 被打包在了一个 OCI 镜像。
这是一个可选步骤。 如果你不打算使用 Docker Hub,请跳过。 但是,如果执行此步骤,则需要一个 Docker ID。 它们是免费的,如果想认真学习和使用 Docker,它们就很重要。
运行以下命令以使用你自己的 Docker ID 标记镜像,以便你可以将其推送到自己的 Docker Hub 存储库。 我的 Docker ID 是 nigelpoulton,所以我将运行下面的命令。
docker image tag docker-wasm:0.1 nigelpoulton/docker-wasm:0.1
使用标记有你的 Docker ID 的镜像,运行以下命令将其推送到 Docker Hub。 请记住替换成自己的 Docker ID。 我第一次尝试时失败了,我不得不执行手动 docker login
并再次运行命令。
docker image push nigelpoulton/docker-wasm:0.1
6b43e0bdf164: Pushed
33b9d7fa88a0: Pushed
4c601df9af6e: Pushed
0.1: digest: sha256:6b43...31f8, size: 526
此时 Wasm 应用被打包为 OCI 镜像并托管在 Docker Hub 上。 注意 OS/ARCH
和 SIZE
字段。
在撰写本文时,你需要 Docker Desktop 的技术预览版才能完成此步骤。 你可以在这篇文章中找到下载链接。
运行以下命令告诉 Docker 运行打包在 OCI 镜像中的 Wasm app。 为了可读性,它是一个打包在多行上的单个命令。
docker container run --rm --name=dockerwasm \
--runtime=io.containerd.wasmedge.v1 \
--platform=wasi/wasm32 \
nigelpoulton/docker-wasm:0.1
flag 是 Docker 如何告诉 containerd 使用 runwasi containerd shim ,它使用 WasmEdge 运行打包在镜像中 Wasm 模块。
输出如下。
Hello, Docker Hub!
恭喜。 你成功使用 Docker 构建、共享和运行了 Wasm app!
现在还是非常早期的阶段,写作本文时(2022 年 11 月),有些内容也许会过时。 实现细节会有变化,一些 CLI flag 也会改变。 例如,--platform=wasi/wasm32
已经计划更改为 wasi/wasm
。
然而,方向很明确,并且能够使用熟悉的 Docker 工具和技能去创建 WebAssembly app 是意义重大的。
我也确信这只是 Docker 和 Wasm 的宏伟前景的很小一步!
如果你觉得 WasmEdge 还不错,别忘了给我们一个 star
https://github.com/WasmEdge/WasmEdge