Skip to content
Cloudflare Docs

Mount R2 buckets with FUSE

Mount R2 buckets as filesystems using FUSE in Containers

FUSE (Filesystem in Userspace) allows you to mount R2 buckets as filesystems within Containers. Applications can then interact with R2 using standard filesystem operations rather than object storage APIs.

Common use cases include:

  • Bootstrapping containers with assets - Mount datasets, models, or dependencies for sandboxes and agent environments
  • Persisting user state - Store and access user configuration or application state without managing downloads
  • Large static files - Avoid bloating container images or downloading files at startup
  • Editing files - Make code or config available within the container and save edits across instances.

Mounting buckets

To mount an R2 bucket, install a FUSE adapter in your Dockerfile and configure it to run at container startup.

This example uses tigrisfs, which supports S3-compatible storage including R2:

Dockerfile

FROM alpine:3.20
# Install FUSE and dependencies
RUN apk update && \
apk add --no-cache 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 ${BUCKET_NAME}..."\n\
/usr/local/bin/tigrisfs --endpoint "${R2_ENDPOINT}" -f "${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
CMD ["/startup.sh"]

The startup script creates a mount point, starts tigrisfs in the background to mount the bucket, and then lists the mounted directory contents.

Passing credentials to the container

Your Container needs R2 credentials and configuration passed as environment variables. Store credentials as Worker secrets, then pass them through the envVars property:

src/index.js
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,
BUCKET_NAME: this.env.R2_BUCKET_NAME,
R2_ACCOUNT_ID: this.env.R2_ACCOUNT_ID,
};
}

The AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY should be stored as secrets, while R2_BUCKET_NAME and R2_ACCOUNT_ID can be configured as variables in your wrangler.jsonc:

{
"vars": {
"R2_BUCKET_NAME": "my-bucket",
"R2_ACCOUNT_ID": "your-account-id"
}
}

Other S3-compatible storage providers

Other S3-compatible storage providers, including AWS S3 and Google Cloud Storage, can be mounted using the same approach as R2. You will need to provide the appropriate endpoint URL and access credentials for the storage provider.

Mounting bucket prefixes

To mount a specific prefix (subdirectory) within a bucket, most FUSE adapters require mounting the entire bucket and then accessing the prefix path within the mount.

With tigrisfs, mount the bucket and access the prefix via the filesystem path:

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 "${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

Your application can then read from /mnt/r2/${BUCKET_PREFIX} to access only the files under that prefix. Pass BUCKET_PREFIX as an environment variable alongside your other R2 configuration.

Mounting buckets as read-only

To prevent applications from writing to the mounted bucket, add the -o ro flag to mount the filesystem as read-only:

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 "${BUCKET_NAME}" /mnt/r2 &\n\
sleep 3\n\
\n\
ls -lah /mnt/r2\n\
' > /startup.sh && chmod +x /startup.sh

This is useful for shared assets or configuration files where you want to ensure applications only read data.