@mastra/docker 0.8.0-alpha.2 → 0.9.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -62,6 +62,105 @@ const workspace = new Workspace({
62
62
  > starts, otherwise the mount fails. Provision it ahead of time (for example,
63
63
  > with a one-off container that creates `conversations/abc123` in the volume).
64
64
 
65
+ ### Templates
66
+
67
+ `DockerTemplate` prepares a reusable environment once — a base image plus ordered
68
+ setup commands, env vars, and package installs — then spawns multiple disposable
69
+ sandboxes from it. Each sandbox is a fresh container with its own writable layer
70
+ over the shared read-only image, so their filesystems are independent. The image
71
+ is produced by synthesizing a `Dockerfile` and running `docker build` (not
72
+ `docker commit`), so setup is baked into reproducible, cached, content-addressed
73
+ layers.
74
+
75
+ ```typescript
76
+ import { DockerSandbox, DockerTemplate } from '@mastra/docker';
77
+
78
+ const template = new DockerTemplate({ baseImage: 'node:22-slim' })
79
+ .aptInstall(['git', 'ca-certificates'])
80
+ .runCmd('git clone --depth=1 https://example.com/repo /workspace/app')
81
+ .setWorkdir('/workspace/app')
82
+ .runCmd('npm ci');
83
+
84
+ // Prepare once, spawn many — each has an independent writable filesystem.
85
+ // The sandbox builds the image on first start() and reuses it afterwards,
86
+ // and its working directory follows the template's last setWorkdir().
87
+ const a = new DockerSandbox({ template });
88
+ const b = new DockerSandbox({ template });
89
+
90
+ // Or build explicitly, e.g. to surface failures before creating sandboxes.
91
+ const result = await template.build();
92
+ if (result.status !== 'ready') throw new Error(result.error);
93
+
94
+ // Remove the built image when done (independent of any sandbox's destroy()).
95
+ await template.dispose();
96
+ ```
97
+
98
+ `template` also accepts an async factory (`() => Promise<DockerTemplate>`),
99
+ resolved once per container-creating `start()`; this is how repository
100
+ templates track a moving branch.
101
+
102
+ Builder methods (`from`, `setWorkdir`, `setEnvs`, `runCmd`, `aptInstall`,
103
+ `pipInstall`, `npmInstall`) are immutable and chainable — each returns a new
104
+ template, and their signatures match the E2B and platform template builders.
105
+ The image tag is content-addressed (`mastra-template:<hash>`), so `build()` is
106
+ idempotent and reuses an existing image unless you pass `{ force: true }`,
107
+ which also bypasses the daemon's layer cache so every step really re-runs.
108
+
109
+ Never put secrets in `setEnvs` — they are baked into the image. For a step that
110
+ needs a credential, use `runWithSecrets`: the command runs in a throwaway build
111
+ stage forked from the steps before it, and only `output` is copied into the
112
+ image. Secret values are passed by value (`new DockerTemplate({ secrets })` or
113
+ `build({ secrets })`, falling back to `process.env`) and never enter the template
114
+ identity. Values are delivered through BuildKit secret mounts, so they never
115
+ land in any layer, history entry, or build-cache metadata — only in a tmpfs
116
+ visible to that one `RUN`. Builds that use secrets require a BuildKit-capable
117
+ daemon (Docker 20.10+).
118
+
119
+ ```typescript
120
+ const template = new DockerTemplate({ secrets: { GITHUB_TOKEN: token } })
121
+ .aptInstall(['git', 'ca-certificates'])
122
+ .runWithSecrets(
123
+ 'git -c http.extraheader="AUTHORIZATION: bearer $GITHUB_TOKEN" clone https://github.com/acme/private.git /workspace/app',
124
+ {
125
+ secrets: ['GITHUB_TOKEN'],
126
+ output: '/workspace/app',
127
+ },
128
+ )
129
+ .setWorkdir('/workspace/app')
130
+ .runCmd('npm ci');
131
+ ```
132
+
133
+ `dispose()` removes the image; Docker refuses while a container still references
134
+ it, so destroy the template's sandboxes first.
135
+
136
+ #### Repository templates
137
+
138
+ `createDockerRepoTemplate` prepares a repository checkout plus setup commands,
139
+ with the same options as the E2B and platform repo templates. It returns a
140
+ template factory for the sandbox's `template` option: on each resolution it
141
+ calls `getRepositoryAccess`, resolves the current head of `ref` (default
142
+ branch when omitted) with `git ls-remote`, and pins that commit into the
143
+ template identity — so a moved branch yields a fresh image for the next sandbox
144
+ while an unmoved one reuses the cached image. The credential is used only for
145
+ the head lookup and the clone stage; it never enters the identity or the image.
146
+
147
+ ```typescript
148
+ import { DockerSandbox, createDockerRepoTemplate } from '@mastra/docker';
149
+
150
+ const sandbox = new DockerSandbox({
151
+ template: createDockerRepoTemplate({
152
+ getRepositoryAccess: async () => ({
153
+ cloneUrl: 'https://github.com/acme/app.git',
154
+ authorization: { scheme: 'bearer', token: await mintInstallationToken() }, // private repos
155
+ }),
156
+ ref: 'main', // branch, tag, or commit; omit for the default branch
157
+ setupCommand: ['npm ci', 'npm run build'],
158
+ buildEnv: { NPM_CONFIG_REGISTRY: 'https://registry.example.com' }, // non-secret, part of the identity
159
+ workingDirectory: '/workspace', // checkout lands at /workspace/app and becomes the cwd
160
+ }),
161
+ });
162
+ ```
163
+
65
164
  ## Documentation
66
165
 
67
166
  - [Docker Sandbox integration guide](https://mastra.ai/integrations/sandboxes/docker)