跳至主要內容

DockerSandbox

在本機的 Docker 容器內執行指令。使用長時間執行的容器,並透過 docker exec 執行指令。適合本機開發、CI/CD、氣隙部署,以及不需要雲端 Sandbox 的成本敏感情境。介面詳情請參閱 WorkspaceSandbox 介面

安裝
「安裝」的直接連結

npm install @mastra/docker

需要在主機上執行 Docker Engine

使用方式
「使用方式」的直接連結

DockerSandbox 加入 Workspace,並指派給 Agent:

import { Agent } from '@mastra/core/agent'
import { Workspace } from '@mastra/core/workspace'
import { DockerSandbox } from '@mastra/docker'

const workspace = new Workspace({
sandbox: new DockerSandbox({
image: 'node:22-slim',
}),
})

const agent = new Agent({
id: 'dev-agent',
name: 'dev-agent',
model: 'anthropic/claude-opus-4-7',
workspace,
})

建構函式參數
「建構函式參數」的直接連結

id?:

string
= Auto-generated
此 Sandbox 執行個體的唯一識別碼。用於以標籤為基礎的重新連線。

name?:

string
= Sandbox 的 `id`
--name 傳遞給 Docker 的容器顯示名稱。[a-zA-Z0-9_.-] 以外的字元會替換為 -;如果結果並非以英數字元開頭,則會加上前綴。

image?:

string
= 'node:22-slim'
容器要使用的 Docker 映像。

command?:

string[]
= ['sleep', 'infinity']
容器進入點指令。必須讓容器持續執行,才能透過 exec 執行指令。

env?:

Record<string, string>
要在容器中設定的環境變數。

volumes?:

Record<string, string>
主機到容器的 bind mount。鍵為主機路徑,值為容器路徑。

network?:

string
要加入的 Docker 網路。

privileged?:

boolean
= false
以特殊權限模式執行。

memory?:

number
以位元組為單位的記憶體限制。Docker 將 0 視為無限制。對應至 Docker HostConfig.Memory。

memorySwap?:

number
以位元組為單位的記憶體與 Swap 總量。對應至 Docker HostConfig.MemorySwap。

cpuShares?:

number
CPU Share 的相對權重。對應至 Docker HostConfig.CpuShares。

cpuQuota?:

number
每個週期的 CPU 配額,單位為微秒。對應至 Docker HostConfig.CpuQuota。

cpuPeriod?:

number
CPU 週期,單位為微秒。對應至 Docker HostConfig.CpuPeriod。

pidsLimit?:

number
容器中的處理程序 ID 數量上限。對應至 Docker HostConfig.PidsLimit。

readonlyRootfs?:

boolean
以唯讀方式掛載容器根檔案系統。對應至 Docker HostConfig.ReadonlyRootfs。

capDrop?:

string[]
要移除的 Linux capability。使用 ['ALL'] 先移除所有 capability,再新增特定項目。對應至 Docker HostConfig.CapDrop。

capAdd?:

string[]
移除後要加回的 Linux capability,例如 NET_BIND_SERVICE。對應至 Docker HostConfig.CapAdd。

securityOpt?:

string[]
Docker 安全性選項,例如 ['no-new-privileges:true']。對應至 Docker HostConfig.SecurityOpt。

ulimits?:

Array<{ name: string; soft: number; hard: number }>
容器的 Ulimit 項目。對應至 Docker HostConfig.Ulimits。

tmpfs?:

Record<string, string>
tmpfs 掛載路徑與選項。對應至 Docker HostConfig.Tmpfs。

workingDir?:

string
= '/workspace'
容器內的工作目錄。

labels?:

Record<string, string>
其他容器標籤。一律包含 Mastra 標籤(mastra.sandbox、mastra.sandbox.id)。

timeout?:

number
= 300000 (5 minutes)
預設指令逾時時間,單位為毫秒。

dockerOptions?:

Docker.DockerOptions
直接傳遞的 dockerode 連線選項,用於自訂 Socket 路徑、遠端主機或 TLS 憑證。

instructions?:

string | function
自訂指示,會覆寫 getInstructions() 傳回的預設指示。傳入空字串可隱藏指示。

屬性
「屬性」的直接連結

id:

string
Sandbox 執行個體識別碼。

name:

string
Provider 名稱('DockerSandbox')。

provider:

string
Provider 識別碼('docker')。

status:

ProviderStatus
'pending' | 'starting' | 'running' | 'stopping' | 'stopped' | 'destroying' | 'destroyed' | 'error'

container:

Container
底層 dockerode Container 執行個體。如果 Sandbox 尚未啟動,則擲回 SandboxNotReadyError。

processes:

DockerProcessManager
背景處理程序管理器。請參閱 SandboxProcessManager 參考

背景處理程序
「背景處理程序」的直接連結

DockerSandbox 內建處理程序管理器,可產生及管理背景處理程序。處理程序透過 docker exec 在容器內執行。

const sandbox = new DockerSandbox({ id: 'dev-sandbox' })
await sandbox._start()

// Spawn a background process
const handle = await sandbox.processes.spawn('node server.js', {
env: { PORT: '3000' },
onStdout: data => console.log(data),
})

// Interact with the process
console.log(handle.stdout)
await handle.sendStdin('input\n')
await handle.kill()

完整 API 請參閱 SandboxProcessManager 參考

環境變數
「環境變數」的直接連結

使用 env 在容器層級設定環境變數。產生處理程序時,也可以傳入個別指令的環境變數:

const sandbox = new DockerSandbox({
image: 'node:22-slim',
env: {
NODE_ENV: 'production',
DATABASE_URL: 'postgres://localhost:5432/mydb',
},
})

Bind mount
「Bind mount」的直接連結

使用 volumes 選項將主機目錄掛載至容器:

const sandbox = new DockerSandbox({
image: 'node:22-slim',
volumes: {
'/my/project': '/workspace/project',
'/shared/data': '/data',
},
})

Bind mount 會在建立容器時套用。主機路徑必須在 Sandbox 啟動前存在。

安全強化
「安全強化」的直接連結

使用 Docker 專屬的資源與安全強化選項來限制 Sandbox 容器。以下範例限制記憶體與處理程序數量,並透過相符的 cpuPeriodcpuQuota 值將 CPU 限制為單一核心。它會移除 Linux capability、將根檔案系統設為唯讀,並把 /tmp 掛載為可寫入的暫存空間:

const sandbox = new DockerSandbox({
image: 'node:22-slim',
memory: 512 * 1024 * 1024,
memorySwap: 512 * 1024 * 1024,
cpuPeriod: 100_000,
cpuQuota: 100_000,
pidsLimit: 256,
readonlyRootfs: true,
capDrop: ['ALL'],
capAdd: ['NET_BIND_SERVICE'],
securityOpt: ['no-new-privileges:true'],
ulimits: [{ name: 'nofile', soft: 1024, hard: 2048 }],
tmpfs: {
'/tmp': 'rw,noexec,nosuid,size=64m',
},
})

這些選項直接對應至 Docker HostConfig 欄位,只有在傳入時才會設定。

啟用安全強化前,請檢視以下取捨:

  • readonlyRootfs:容器內套件安裝,以及寫入掛載路徑以外位置的工具可能會失敗。為 /tmp 這類可寫入的暫存路徑新增 tmpfs 項目;需要時,也請為 ~/.npm 這類套件管理器快取掛載 tmpfs 或 Volume。
  • capDrop:移除所有 capability 會停用需要 Linux capability 的指令,包括 ping 與掛載操作。以 FUSE 為基礎的工具也會停用。只加回工作負載所需的 capability。
  • memory:Docker 將 0 視為無限制。只有在不需要限制記憶體時,才省略 memory 或傳入 0
  • memorySwap:Docker 的記憶體與 Swap 行為取決於主機和 Docker Daemon 設定。設定 memory 而未設定 memorySwap 時,Docker 預設允許使用最多為記憶體限制兩倍的 Swap。若要停用容器 Swap,請將 memorySwap 設為與 memory 相同;Docker 也接受 -1,表示 Swap 無限制。
  • pidsLimit:非常低的值可能會使 docker exec 工作負載失效,因為每個指令都會在長時間執行的容器內啟動額外處理程序。
  • privileged:特殊權限容器會略過 capability 與安全性選項控制。除非工作負載需要,否則不要將 privileged: true 與 capability 或安全性選項搭配使用。
  • 重新連線:Sandbox ID 相符時,DockerSandbox 會重複使用現有容器;若檢查到的 HostConfig 安全強化值不同,則會發出警告。請銷毀並重新建立 Sandbox,以套用變更後的安全強化選項。Docker 可能會正規化檢查到的值;如果原始容器使用 Docker 預設的 Swap 行為,在重新連線時變更 memorySwap 可能會觸發警告。
  • Docker Desktop:資源限制會套用於 macOS 與 Windows 上的 Docker Desktop 虛擬機器內,因此 VM 設定的資源可能會限制容器可獲得的資源。

重新連線
「重新連線」的直接連結

DockerSandbox 可以透過比對標籤重新連線至現有容器。呼叫 start() 時,它會檢查是否有 mastra.sandbox.id 標籤與 Sandbox ID 相符的容器。如果找到:

  • 執行中的容器會直接重複使用。
  • 已停止的容器會重新啟動。
// First run — creates a new container
const sandbox = new DockerSandbox({ id: 'persistent-sandbox' })
await sandbox._start()

// Later — reconnects to the existing container
const sandbox2 = new DockerSandbox({ id: 'persistent-sandbox' })
await sandbox2._start()

Docker 連線選項
「Docker 連線選項」的直接連結

透過 dockerOptions 連線至遠端 Docker 主機,或使用自訂 Socket 路徑:

// Remote Docker host
const sandbox = new DockerSandbox({
dockerOptions: {
host: '192.168.1.100',
port: 2376,
ca: fs.readFileSync('ca.pem'),
cert: fs.readFileSync('cert.pem'),
key: fs.readFileSync('key.pem'),
},
})

// Custom socket path
const sandbox = new DockerSandbox({
dockerOptions: {
socketPath: '/var/run/docker.sock',
},
})