Docker是现在,WASM是未来,Docker+WASM的结合

查理谈科技 2024-05-08 00:27:25

Docker最近宣布集成WASM(WebAssembly)技术,并随后发布了技术预览版,引起了开发者社区许多人的兴趣。

然而,有人猜测这种集成对软件开发的未来意味着什么,一些博客文章声称 WASM 将取代 Docker、Kubernetes 和其他广泛使用的技术。

Docker 的创始人 Solomon Hykes 也在推文中评论了这一发展,表示如果 WASM 和 WASI(WebAssembly System Interface)在 2008 年就已经可用,那么 Docker 就不再是必要的了。 该声明强调了 WASM 集成对软件开发行业的潜在影响。

从那时起,开发人员一直在问很多有关 WASM 的问题,包括它与 Docker 有何关系、Docker 和 WASM 之间的区别以及 WASM 是否会取代 Docker、Kubernetes,或两者兼而有之。 在这里,我们将系统回顾Docker 和WASM的知识,并尝试理解这两者的关系。

什么是 WASM?

首先,简单地了解一下 WebAssembly (WASM) 是什么。 如果之前在电脑上使用过Photoshop的,就会知道在电脑上使用Photoshop的话,必须先把Photoshop这种大型应用程序下载到桌面上。 现在,随着云计算的发展,我们可以不需要下载应用并安装到本地,无需任何安装或配置就可以直接在网络浏览器中访问这些工具, 这就是 WASM 发挥作用的地方。

传统的 Web 应用程序是使用 HTML、CSS 和 JavaScript 框架(例如 React 或 VueJS)构建的。 虽然这些工具可以创建漂亮的网页和游戏,但它们也有其局限性。 Photoshop 和高端视频游戏等复杂应用程序通常使用 C、C++ 或 Rust 等编程语言开发,并作为可执行的 deskt0p 应用程序运行。

但通过 WASM,这些复杂的应用程序可以移植到浏览器中在线工作。 它本质上是一种可以与传统网络语言一起使用的新型代码。 WASM 允许开发人员用其他编程语言编写代码并编译以在浏览器中运行。 这意味着,我们现在可以直接在网络浏览器中访问 Photoshop、Figma 等应用程序或玩高端游戏,无需任何安装或配置。

传统上,编程语言是以计算机无法理解的格式编写的。 因此,我们需要通过一个称为编译的过程,将用编程语言编写的源代码转换为机器可以理解的代码。 转换后的代码格式称为编译目标。

WebAssembly 是 C、C++ 和 Rust 等语言的新型编译目标,用于在 Web 浏览器中运行本机应用程序。 要创建 WebAssembly 二进制文件 (.wasm),需要使用在线汇编器(例如 WASMExplorer 或 WASMFiddle)或 Emscripten 等工具来编译本机代码。

生成的二进制文件可以与 Javascript 代码一起在浏览器中加载和运行,并且可以使用 Javascript WebAssembly API 与 Javascript 代码进行交互。 这使得高性能应用程序(如本机桌面程序、视频游戏和图像编辑器)可以直接在 Web 浏览器中运行,无需任何额外的安装或插件。

WASM 的Hello World 例子

首先,我们将学习如何编译一个简单的 C 程序,并在本地运行它。 然后,我们将相同的程序编译为 WebAssembly (WASM) 二进制文件并在网页中运行它。

下面是用 C 编写的基本“Hello World”程序的代码,该程序将文本打印到屏幕上。

#include <stdio.h>int main() { printf("Hello World\n"); return 0;}

下一步,使用 GCC 将其编译为二进制文件,然后我们可以运行生成的“helloworld.exe”文件。

正如预期的那样,当执行文件(helloworld.exe)时,它会在屏幕上显示“Hello World”。

接下来,将相同的程序编译为 WASM 二进制文件并在浏览器中运行它。 为此, 这里使用 EmScripten 工具,按照该工具网站上的说明(https://emscripten.org/docs/getting_started/Tutorial.html)进行操作,先安装emscripten:

# Get the emsdk repogit clone https://github.com/emscripten-core/emsdk.git# Enter that directorycd emsdk

使用“emcc”命令,我们编译“helloworld.c”文件并生成 WASM 二进制文件。

# 获取最新版本的emsdk(第一次克隆时不需要)git pull# 下载并安装最新的 SDK 工具。./emsdk install latest# 使“最新”SDK 对当前用户“有效”。 (写入 .emscripten 文件)./emsdk activate latest# 使“最新”SDK 对当前用户“有效”。 (写入 .emscripten 文件)source ./emsdk_env.sh

使用 Emscripten 编译器前端 (emcc) 访问 Emscripten。 该脚本调用构建代码所需的所有其他工具,并且可以充当 gcc 或 clang 等标准编译器的直接替代品。 使用 ./emcc 或 ./em++ 在命令行上调用它。

在这里,对于这个helloworld.c 程序, 使用如下命令编译成wasm:

emcc helloworld.c -o helloworld.html

另一个有用的选项是“-o”标志,它会生成一个 HTML 文件,其中包含所需的支持 JavaScript 代码,用来加载 WASM 二进制文件。

运行结果如下:

使用“emcc”命令,Emscripten会自动生成“helloworld.html”、“helloworld.js”和“helloworld.wasm”文件。

生成的文件如下:

如果仔细查看 JS 文件,您会发现 WASM 二进制文件已作为文件加载到网页中。

helloworld.js

当我们查看 HTML 文件时,C 代码将被执行,预期的输出将打印在页面上。

因此,我们成功地将相同的 C 代码编译成 WASM 二进制文件,并将其加载到网页中。

helloworld.html

运行这个WASM文件有两种方式, 本地可以通过node.js 来运行:

node helloworld.js

如果想运行helloworld.html 来运行helloworld.js, 直接在本地Chrome浏览器加载helloworld.html是不行的, 目前的浏览器并不支持加载本地的wasm 文件:

因此可以需要把这个helloworld.html 文件存放到Web服务器上, 这里是网址:https://www.zwchen.com/wasm/helloworld.html

浏览器之外的 WASM

通过上面的例子,现在我们了解了 WebAssembly 是如何在浏览器中运行的。 下面开始探索WASM如何在Web环境(浏览器)之外运行。

如果 WebAssembly 擅长在浏览器上打包和运行应用程序,为什么不使用它在任何地方(甚至在 Web 之外)打包和运行应用程序呢?

当您将以 Go、Rust 或 C++ 等语言编写的应用程序编译为 WebAssembly 格式时,您将获得可以在任何 WASM 运行时(例如 wagi、WebAssembly、Micro Runtime、Wasmtime 或 Wasmedge)上执行的二进制文件。

WebAssembly 运行时类似于 JVM、V8 引擎、Ruby 或 Python 运行时,能够运行用这些特定语言编写的应用程序。

WebAssembly 二进制文件与平台无关,因此您无需担心底层操作系统或处理器架构。 该应用程序可以在所有主要操作系统上运行。 但是,应用程序可能需要访问系统资源,例如文件和目录、环境变量或系统时间。 这些资源在启动期间使用 WebAssembly 系统接口 (WASI) 绑定到 WASM 模块。

操作系统和 WebAssembly 系统接口(帮助 WASM 运行时访问系统资源)协同工作,允许 WebAssembly 二进制文件在它们之上运行。

此外,无需担心二进制文件是在 Intel 还是 ARM 处理器上运行,因为 WebAssembly 模块在 WASM 运行时内运行,并根据当前主机操作系统和处理器执行 WASM 二进制文件。

因此,WASM 是应用程序及其依赖项的打包形式,其格式可以在浏览器上运行,而 WASI 是系统接口,使 WASM 可以在浏览器之外和任何操作系统上运行。

什么是 Docker?

如果您还不熟悉“Docker”,让我们快速了解一下。

在之前的演示中,我们在本地计算机上执行了一个简单的 C 程序,其中涉及多个步骤。 我们必须下载并安装与我们的操作系统兼容的 C/C++ 编译器,安装必要的库和依赖项,配置路径变量以从文件系统中的任何位置使用“GCC”命令,使用以下命令编译源程序 正确的 GCC 命令并运行生成的可执行文件。

例如,如果您在 Windows 计算机上运行此 Hello World 程序,则必须下载并安装与 Windows 操作系统兼容的 C/C++ 编译器、依赖项和库。 此外,您还必须将 GCC 命令添加到 Windows 路径变量中。

但是,如果您的同事想在他们的 Linux 或 Mac 系统上运行并检查您的程序怎么办? 您可以与他们共享 C 源文件,但他们必须从一开始就处理程序的编译和运行。 他们需要下载并安装适合其特定操作系统的兼容 C 编译器、库和依赖项。

如果您在 C 程序中使用了与其操作系统版本不兼容的库,则会造成额外的困难。

历史上,这一直是开发、构建和交付软件中最令人头痛的问题之一。 您最终会对团队中的每个人说“好吧,它可以在我的机器上运行”。

这就是 Docker 的用武之地。Docker 允许您将程序以及所有必要的依赖项、库等打包到单个容器中。 然后,您可以将此容器提供给您的同事,他们可以运行它,无论其底层硬件基础设施或操作系统如何。

Docker 能够在操作系统和硬件基础设施之上的虚拟机内运行一个或多个容器。 每个容器都可以与其他容器以及底层操作系统和服务通信,但在完全隔离的环境中运行。

实际上,Docker 容器基于 docker 镜像,它是一组文件系统的快照,这些快照分层在一起形成单个环境。 在我们的示例中,我们可以从基础映像开始创建一个 docker 映像,添加 Hello World C 程序所需的支持程序、文件、实用程序、编译器(例如 C/C++)和库。 最后,我们可以添加 C 源程序并将其捆绑为可用于运行 Docker 容器的单个 docker 映像。

在这里,继续沿用上面的C语言的Hello World的例子,完成创建和运行 Docker 容器的步骤。通过遵循这些步骤,可以基本了解如何使用 Docker 进行部署和运行HelloWorld 代码。

开发目标是容器化一个简单的 C 程序。 为了实现这一目标,首先要制作 Dockerfile 来创建 Docker 映像:

FROM gcc:latestCOPY . /WasmDemoWORKDIR /WasmDemo/RUN gcc -o wasmdemoprogram helloworld.cCMD ["./wasmdemoprogram"]

Dockerfile 首先使用包含 C 编译器的“gcc”映像。 随后的几行利用 Docker 的 COPY 指令将代码从本地目录传输到镜像中。然后,我们通过 Docker 的 RUN 指令使用“gcc”命令构建映像。 最后,利用CMD指令指定容器运行时要执行的命令。

构建镜像后,执行“docker build”命令来构建它,然后执行 docker run 命令来执行应用程序。

docker build -t c-program-inside-docker ./

运行结果:

运行这个镜像:

docker run -it c-program-inside-docker

结果:

虽然有其他更高级的方法可用于将构建过程与可执行版本分开,但为了简单起见,我们不会在此讨论它们。

Docker 与 WASM

在本次比较中,我们将探讨 Docker 和 WebAssembly (WASM) 之间的差异。 您可能已经注意到,Docker 和 WASM 都具有类似的功能。 他们可以打包应用程序并允许它们在各种环境中运行。

在架构方面,Docker 从底层基础设施开始,然后是主机操作系统、Docker 引擎,最后是包含应用程序的库、依赖项和二进制文件的容器。

查看 WebAssembly (WASM) 架构图,您将看到与 Docker 类似的层次结构。 它从基础设施开始,然后是主机操作系统,然后是 WebAssembly 系统接口(WASI),它为 WASM 运行时提供对系统资源的访问。 最后,“WASM”运行时运行 WASM 模块。

经过仔细检查,Docker 和 WASM 之间存在一些显著差异:

Docker 将程序及其依赖项打包到一个容器中,由 Docker 引擎执行。 Docker 容器包括完整的文件、系统、实用程序、二进制文件和库,使其看起来像应用程序的完整操作系统。

创建与正确的系统架构(例如 Intel、ARM 或 AMD)相匹配的 Docker 镜像至关重要。 例如,如果您使用 Docker 运行 Raspberry Pi OS,则必须基于 Linux 映像为 C 程序创建 Docker 映像,并将其编译为 ARM 处理器架构。 否则容器将无法正常运行。

另一方面,WASM 模块是 C、C++、Rust 或 Go 应用程序的预编译二进制文件,可以在 WebAssembly 运行时(例如 Wasmtime、Wasmedge 或 Wagi)上轻松执行。 WASM 二进制文件不依赖于主机操作系统或处理器架构,因为它们不包含任何预打包的文件系统或低级操作系统原语。

相反,每个目录、环境变量、时钟、实用程序和系统资源在运行时都通过 Web Assembly 系统接口 (WASI) 连接到 WASM 模块。 因此,WASM 模块不与主机操作系统或处理器架构耦合。

从性能角度来看,WASM 比 Docker 有几个显着的优势。 WASM 二进制文件的启动时间为几毫秒,而 Docker 容器的启动时间为几秒。 WASM 程序在性能方面接近本机速度,并且 WASM 模块的大小通常只有几 MB,因为它没有任何操作系统组件。 相比之下,容器映像可能有数十或数百 MB,尤其是在存在许多依赖于操作系统的包的情况下。 由于 WASM 是为浏览器构建的,因此它也可以在浏览器中运行。 两者之间的一个关键区别是 WASM 跨平台运行,而 Docker 对特定 CPU 架构或操作系统有限制。 例如,Windows 容器本身并不在 Linux 上运行,反之亦然。

比较点

WASM

容器(Container)

体积

几MB

一般10到100MB

启动时间

毫秒级

秒级

性能速度

几乎原生速度

与原生速度相差甚远

在 Web 浏览器中运行

可以

不可以

跨平台/可移植性

特定于CPU架构

标准

W3C 和 OCI标准

OCI标准

系统交互

使用WASI访问底层OS

容器本身包含操作系统和文件系统

WASM 和 Docker 集成

如上所示,WebAssembly (WASM) 是一个强大的工具,用于在浏览器或任何 WASM 运行时编译和执行用 C、C++、Rust 或 Go 等语言编写的现有本机代码,具有接近本机的性能、高安全性和更快的速度、启动时间。

Docker 允许将应用程序代码及其必要的依赖项打包到单个映像中,使其具有高度可移植性并提供运行时隔离。 在过去的十年中,大量的企业投入了大量资金来了解 Docker 容器并构建支持它们的基础设施,例如 swarm 和 Kubernetes 集群。

那么,现在是否应该放弃所有这些知识和基础设施并从头开始学习 WASM? 答案是:不必要。

如果我们将 WASM 的高性能、安全性和更快的启动时间与 Docker 的高可移植性特性结合起来会怎么样?

Docker 和 WASM 的集成可能比我们想象的更有价值。 借助 Docker 的 WASM 支持,您可以与 Linux 和 Windows 容器并行运行 WASM 容器,从而允许您在 WASM 容器中运行本机应用程序代码并将其作为 Docker 映像进行共享。

0 阅读:0

查理谈科技

简介:感谢大家的关注