强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

WebAssembly 入门教程 / 13 - Docker 与容器

13 - Docker 与容器

Docker + Wasm = 比传统容器更轻量、更安全、启动更快的容器化方案。


13.1 Docker 对 Wasm 的支持

背景

2022 年 10 月,Docker 宣布与 Wasm 集成。这意味着可以直接在 Docker Desktop 中运行 Wasm 容器。

传统容器 vs Wasm 容器

传统 Linux 容器:
┌─────────────────────┐
│ 应用进程              │
│ ├── bin/              │
│ ├── lib/              │
│ ├── lib64/            │  完整的 Linux 用户空间
│ ├── usr/              │  通常 100MB+
│ ├── etc/              │
│ └── ...               │
├─────────────────────┤
│ 容器运行时 (runc)     │
├─────────────────────┤
│ Linux 内核 (namespaces│
│ + cgroups)            │
└─────────────────────┘

Wasm 容器:
┌─────────────────────┐
│ Wasm 模块             │
│ (单个 .wasm 文件)     │  通常 1-10MB
├─────────────────────┤
│ Wasm 运行时           │
│ (containerd-shim-    │  无完整 Linux 用户空间
│  wasmedge/wasmtime)   │
├─────────────────────┤
│ Linux 内核            │
└─────────────────────┘

对比

特性传统容器Wasm 容器
镜像大小50MB - 1GB+1MB - 20MB
冷启动时间100ms - 数秒< 1ms
内存占用数十 MB数 MB
安全模型Namespace + CgroupWasm 沙箱
跨平台依赖 CPU 架构天然跨平台
系统调用直接访问内核通过 WASI

13.2 使用 Docker Desktop 运行 Wasm

前置条件

# 1. 安装 Docker Desktop 4.15+
# 2. 启用 Wasm 运行时
# Docker Desktop → Settings → Features in development → ✅ Enable Wasm

# 或使用命令行
docker run --runtime=io.containerd.wasmedge.v1 \
  --platform wasi/wasm32 \
  hello-wasm

创建 Wasm 容器镜像

# Dockerfile.wasm
FROM scratch
COPY app.wasm /app.wasm
ENTRYPOINT ["/app.wasm"]
# 构建镜像
docker build --platform wasi/wasm32 -t my-wasm-app -f Dockerfile.wasm .

# 运行
docker run --runtime=io.containerd.wasmedge.v1 \
  --platform wasi/wasm32 \
  my-wasm-app

使用 Rust 构建 Wasm 应用

// src/main.rs
fn main() {
    println!("Hello from Wasm container!");
    
    // 读取环境变量
    if let Ok(msg) = std::env::var("MESSAGE") {
        println!("Message: {}", msg);
    }
    
    // 读取文件
    if let Ok(content) = std::fs::read_to_string("/data/input.txt") {
        println!("File content: {}", content);
    }
}
# 多阶段构建
FROM rust:1.77 AS builder
WORKDIR /app
COPY . .
RUN rustup target add wasm32-wasi && \
    cargo build --target wasm32-wasi --release

FROM scratch
COPY --from=builder /app/target/wasm32-wasi/release/app.wasm /app.wasm
ENTRYPOINT ["/app.wasm"]

13.3 containerd shim 运行时

可用的 Wasm shim

shim运行时说明
containerd-shim-wasmedge-v1WasmEdge高性能,AI 推理
containerd-shim-wasmtime-v1Wasmtime参考实现,完整 WASI
containerd-shim-wasmer-v1Wasmer多后端
spinSpinFermyon 微服务框架
slightSpiderLightningDeis Labs

安装 containerd shim

# 安装 WasmEdge shim
curl -sSf https://raw.githubusercontent.com/nicedoc/nicedoc.io/master/install.sh | bash

# 配置 containerd
cat >> /etc/containerd/config.toml << EOF
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.wasm]
  runtime_type = "io.containerd.wasmedge.v1"
EOF

# 重启 containerd
sudo systemctl restart containerd

13.4 Kubernetes 中的 Wasm

使用 runwasi 在 K8s 中运行 Wasm

# RuntimeClass 定义
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: wasmedge
handler: wasmedge
---
# Pod 使用 Wasm RuntimeClass
apiVersion: v1
kind: Pod
metadata:
  name: wasm-app
spec:
  runtimeClassName: wasmedge
  containers:
    - name: app
      image: my-registry/my-wasm-app:latest
      env:
        - name: MESSAGE
          value: "Hello from K8s"
      resources:
        limits:
          memory: "64Mi"
          cpu: "100m"

Kwok + Wasm 测试集群

# 使用 kind 创建支持 Wasm 的集群
kind create cluster --config=- <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
    extraMounts:
      - hostPath: /usr/local/bin/containerd-shim-wasmedge-v1
        containerPath: /usr/local/bin/containerd-shim-wasmedge-v1
EOF

13.5 WasmCloud

WasmCloud 是一个专为 Wasm 设计的分布式应用平台,基于 Actor 模型。

核心概念

WasmCloud 架构:
┌────────────────────────────────────────┐
│              Lattice (网格)              │
│  ┌──────────┐  ┌──────────┐            │
│  │ Actor     │  │ Actor     │            │
│  │ (业务逻辑) │  │ (业务逻辑) │            │
│  └────┬─────┘  └────┬─────┘            │
│       │              │                  │
│  ┌────▼──────────────▼─────┐           │
│  │      Capability          │           │
│  │  (HTTP, DB, MQ, etc.)   │           │
│  └──────────────────────────┘           │
└────────────────────────────────────────┘

Actor(业务逻辑)

use wasmcloud_actor_httpserver::*;
use wasmcloud_actor_messaging::*;

#[derive(Debug, Default, Actor, HealthResponder)]
#[contracts(HttpServer, Messaging)]
pub struct MyActor {}

#[async_trait]
impl HttpServer for MyActor {
    async fn handle_request(&self, ctx: &Context, req: &HttpRequest) -> RpcResult<HttpResponse> {
        let response = match req.path.as_str() {
            "/hello" => HttpResponse::ok("Hello from WasmCloud!"),
            "/health" => HttpResponse::ok(r#"{"status":"healthy"}"#),
            _ => HttpResponse::not_found(),
        };
        Ok(response)
    }
}

Capability Provider

# wasmcloud.toml
name = "my-actor"
language = "rust"
type = "actor"
version = "0.1.0"

[actor]
claims = ["wasmcloud:httpserver", "wasmcloud:messaging"]
# 构建
wash build

# 本地开发
wash dev

# 部署到 lattice
wash app deploy wadm.yaml

13.6 Docker Compose 示例

# docker-compose.yaml
version: "3.9"

services:
  api-gateway:
    image: my-registry/api-gateway:latest
    platform: wasi/wasm32
    runtime: io.containerd.wasmedge.v1
    ports:
      - "8080:8080"
    environment:
      - LOG_LEVEL=info

  auth-service:
    image: my-registry/auth:latest
    platform: wasi/wasm32
    runtime: io.containerd.wasmedge.v1
    environment:
      - JWT_SECRET=secret123

  cache:
    image: redis:7-alpine
    ports:
      - "6379:6379"

13.7 轻量容器场景

Serverless / FaaS

# Knative Service 使用 Wasm 容器
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: wasm-function
spec:
  template:
    spec:
      runtimeClassName: wasmedge
      containers:
        - image: my-registry/function:latest
          resources:
            limits:
              memory: "32Mi"
              cpu: "50m"

IoT 网关

IoT 设备 (ARM64):
┌─────────────────────────┐
│ containerd + Wasm shim  │
│ ┌─────────────────────┐ │
│ │ Wasm 容器:           │ │
│ │ • 传感器数据采集      │ │  同一 .wasm 文件
│ │ • 边缘预处理         │ │  无需交叉编译
│ │ • 异常检测           │ │
│ └─────────────────────┘ │
└─────────────────────────┘

13.8 镜像优化

最小镜像大小

# 最小 Wasm 容器镜像
FROM scratch
COPY --chmod=755 app.wasm /app.wasm
ENTRYPOINT ["/app.wasm"]
# 对比镜像大小
docker images
# REPOSITORY     TAG      SIZE
# node-app       latest   180MB    ← Node.js 容器
# python-app     latest   120MB    ← Python 容器
# go-app         latest   12MB     ← Go 容器
# wasm-app       latest   2.5MB    ← Wasm 容器 ✓

压缩 Wasm 二进制

# wasm-opt 优化
wasm-opt -Oz app.wasm -o app_opt.wasm

# Brotli 压缩(Docker 会自动解压)
brotli app.wasm -o app.wasm.br

# 对比
ls -lh app.wasm app_opt.wasm
# 1.2M app.wasm
# 800K app_opt.wasm

13.9 安全优势

沙箱对比

传统容器攻击面:
┌──────────────────┐
│ 应用进程          │
│   ↓ 系统调用      │
│ Linux 内核        │  ← 内核漏洞可导致逃逸
│   ↓ 硬件          │
│ 宿主机            │
└──────────────────┘

Wasm 容器攻击面:
┌──────────────────┐
│ Wasm 模块         │
│   ↓ WASI 调用     │  ← 只有有限的系统调用
│ Wasm 运行时       │  ← 能力受限的沙箱
│   ↓ 系统调用      │
│ Linux 内核        │  ← 双重隔离
│   ↓ 硬件          │
│ 宿主机            │
└──────────────────┘

13.10 注意事项

⚠️ 生态成熟度:Docker + Wasm 仍在快速演进中,生产使用需要充分测试。

⚠️ 运行时选择:不同 shim 运行时的行为可能有差异,选择时需要考虑完整性和性能。

⚠️ 网络限制:WASI Preview 1 的网络支持有限,需要 Preview 2 或特定扩展。

⚠️ 调试工具:Wasm 容器的调试工具链不如传统容器成熟,需要提前评估。


13.11 扩展阅读


下一章14 - 性能与优化 — 深入理解 Wasm 性能特征并掌握优化技巧。