FUSE (Filesystem in Userspace) 允许您将 R2 buckets 作为文件系统在 Containers 中挂载。然后应用程序可以使用标准的文件系统操作与 R2 交互,而不是使用对象存储 API。
常见用例包括:
- 引导带有资产的容器 - 为沙盒和代理环境挂载数据集、模型或依赖项
- 持久化用户状态 - 存储和访问用户配置或应用程序状态,而无需管理下载
- 大型静态文件 - 避免容器映像膨胀或在启动时下载文件
- 编辑文件 - 在容器内提供代码或配置,并跨实例保存编辑内容。
要挂载 R2 存储桶,请在 Dockerfile 中安装 FUSE 适配器并将其配置为在容器启动时运行。
本示例使用支持包含 R2 在内的 S3 兼容存储的 tigrisfs ↗:
Dockerfile
FROM alpine:3.20
# Install FUSE and dependencies
RUN apk add --no-cache \
--repository http://dl-cdn.alpinelinux.org/alpine/v3.20/main \
ca-certificates fuse curl bash
# Install tigrisfs
RUN ARCH=$(uname -m) && \
if [ "$ARCH" = "x86_64" ]; then ARCH="amd64"; fi && \
if [ "$ARCH" = "aarch64" ]; then ARCH="arm64"; fi && \
VERSION=$(curl -s https://api.github.com/repos/tigrisdata/tigrisfs/releases/latest | grep -o '"tag_name": "[^"]*' | cut -d'"' -f4) && \
curl -L "https://github.com/tigrisdata/tigrisfs/releases/download/${VERSION}/tigrisfs_${VERSION#v}_linux_${ARCH}.tar.gz" -o /tmp/tigrisfs.tar.gz && \
tar -xzf /tmp/tigrisfs.tar.gz -C /usr/local/bin/ && \
rm /tmp/tigrisfs.tar.gz && \
chmod +x /usr/local/bin/tigrisfs
# Create startup script that mounts bucket and runs a command
RUN printf '#!/bin/sh\n\
set -e\n\
\n\
mkdir -p /mnt/r2\n\
\n\
R2_ENDPOINT="https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com"\n\
echo "Mounting bucket ${R2_BUCKET_NAME}..."\n\
/usr/local/bin/tigrisfs --endpoint "${R2_ENDPOINT}" -f "${R2_BUCKET_NAME}" /mnt/r2 &\n\
sleep 3\n\
\n\
echo "Contents of mounted bucket:"\n\
ls -lah /mnt/r2\n\
' > /startup.sh && chmod +x /startup.sh
EXPOSE 8080
CMD ["/startup.sh"]启动脚本创建一个挂载点,在后台启动 tigrisfs 以挂载存储桶,然后列出挂载的目录内容。
您的 Container 需要 R2 credentials 并且需要将配置作为环境变量传递。将凭据存储为 Worker secrets,然后通过 envVars 属性传递它们:
import { Container, getContainer } from "@cloudflare/containers";
export class FUSEDemo extends Container {
defaultPort = 8080;
sleepAfter = "10m";
envVars = {
AWS_ACCESS_KEY_ID: this.env.AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY: this.env.AWS_SECRET_ACCESS_KEY,
R2_BUCKET_NAME: this.env.R2_BUCKET_NAME,
R2_ACCOUNT_ID: this.env.R2_ACCOUNT_ID,
};
}import { Container, getContainer } from "@cloudflare/containers";
interface Env {
FUSEDemo: DurableObjectNamespace<FUSEDemo>;
AWS_ACCESS_KEY_ID: string;
AWS_SECRET_ACCESS_KEY: string;
R2_BUCKET_NAME: string;
R2_ACCOUNT_ID: string;
}
export class FUSEDemo extends Container<Env> {
defaultPort = 8080;
sleepAfter = "10m";
envVars = {
AWS_ACCESS_KEY_ID: this.env.AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY: this.env.AWS_SECRET_ACCESS_KEY,
R2_BUCKET_NAME: this.env.R2_BUCKET_NAME,
R2_ACCOUNT_ID: this.env.R2_ACCOUNT_ID,
};
}AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY 应作为秘密存储,而 R2_BUCKET_NAME 和 R2_ACCOUNT_ID 可以配置为您的 wrangler.jsonc 中的变量:
{
"vars": {
"R2_BUCKET_NAME": "my-bucket",
"R2_ACCOUNT_ID": "your-account-id"
}
}其他兼容 S3 的存储提供商(包括 AWS S3 和 Google Cloud Storage)也可以使用与 R2 相同的方法进行挂载。您将需要提供相应的端点 URL 和存储提供商的访问凭据。
要挂载存储桶内的特定前缀(子目录),大多数 FUSE 适配器需要挂载整个存储桶,然后访问挂载中的前缀路径。
使用 tigrisfs 挂载存储桶并通过文件系统路径访问前缀:
RUN printf '#!/bin/sh\n\
set -e\n\
\n\
mkdir -p /mnt/r2\n\
\n\
R2_ENDPOINT="https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com"\n\
/usr/local/bin/tigrisfs --endpoint "${R2_ENDPOINT}" -f "${R2_BUCKET_NAME}" /mnt/r2 &\n\
sleep 3\n\
\n\
echo "Accessing prefix: ${BUCKET_PREFIX}"\n\
ls -lah "/mnt/r2/${BUCKET_PREFIX}"\n\
' > /startup.sh && chmod +x /startup.sh您的应用程序可以从 /mnt/r2/${BUCKET_PREFIX} 读取以仅访问该前缀下的文件。将 BUCKET_PREFIX 与您的其他 R2 配置一起作为环境变量传递。
为防止应用程序写入已挂载的存储桶,请添加 -o ro 标志以将文件系统挂载为只读:
RUN printf '#!/bin/sh\n\
set -e\n\
\n\
mkdir -p /mnt/r2\n\
\n\
R2_ENDPOINT="https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com"\n\
/usr/local/bin/tigrisfs --endpoint "${R2_ENDPOINT}" -o ro -f "${R2_BUCKET_NAME}" /mnt/r2 &\n\
sleep 3\n\
\n\
ls -lah /mnt/r2\n\
' > /startup.sh && chmod +x /startup.sh这对于共享资产或配置文件非常有用,您希望确保应用程序仅读取数据。
- Container environment variables - 了解如何将秘密和变量传递给 Containers
- tigrisfs ↗ - 用于包含 R2 在内的 S3 兼容存储的 FUSE 适配器
- s3fs ↗ - 用于 S3 兼容存储的替代 FUSE 适配器
- gcsfuse ↗ - 用于 Google Cloud Storage 存储桶的 FUSE 适配器