From c9e7ce8faab3a42c8552a7019fbbcd9a5c6121f1 Mon Sep 17 00:00:00 2001 From: Jakub Dobry Date: Fri, 26 Sep 2025 14:31:24 +0200 Subject: [PATCH 1/2] improve template caches invalidation --- docs.json | 1 + template/caching.mdx | 84 ++++++++++++++++++++ template/customization/defining-template.mdx | 25 +----- template/how-it-works.mdx | 21 +---- 4 files changed, 88 insertions(+), 43 deletions(-) create mode 100644 template/caching.mdx diff --git a/docs.json b/docs.json index 57186d5..732b55e 100644 --- a/docs.json +++ b/docs.json @@ -19,6 +19,7 @@ "pages": [ "template/quickstart", "template/how-it-works", + "template/caching", { "group": "Customization", "icon": "wand-magic-sparkles", diff --git a/template/caching.mdx b/template/caching.mdx new file mode 100644 index 0000000..aec5b99 --- /dev/null +++ b/template/caching.mdx @@ -0,0 +1,84 @@ +--- +title: "Caching" +description: "How the caching process works" +icon: "layer-group" +--- + +The caching concept is similar to [Docker's layer caching](https://docs.docker.com/build/cache/). For each layer command (`.copy()`, `.runCmd()`, `.setEnvs()`, etc.), we create a new layer on top of the existing. +Each layer is cached based on the command and its inputs (e.g., files copied, command executed, environment variables set). +If a layer command is unchanged and its inputs are the same as in any previous build, we reuse the cached layer instead of rebuilding it. + +This significantly speeds up the build process, especially for large templates with many layers. +The cache is scoped to the team, so even if you have multiple templates, they can share the same cache if they have identical layers. + +## Invalidation +You can invalidate the caches only partially, or for the whole template. + +### Partial +Force rebuild from the next instruction, use the method: + + + +```typescript +template.skipCache() +``` + +```python +template.skip_cache() +``` + + + +This will force rebuild from the next instruction, invalidating the cache for all subsequent instructions in the template. + +### Whole Template +To force rebuild the whole template, you can use also `skipCache`/`skip_cache` parameter in the `Template.build` method: + + + +```typescript wrap highlight={3} +Template.build(template, { + alias: 'my-template', + skipCache: true, // Configure cache skip (except for files) +}) +``` + +```python wrap highlight={4} +Template.build( + template, + alias="my-template", + skip_cache=True, # Configure cache skip (except for files) +) +``` + + + +This will skip the cache usage for the whole template build. + +## Files Caching +When using the `.copy()` command, we cache the files based on their content. If the files haven't changed since the last build, we reuse them from the files cache. + +We differ from Docker here. Because we build the template on our infrastructure, we use improved caching on files level. +Even if you invalidate the layer before `.copy()` (e.g., by changing ENV variables), we'll reuse the already uploaded files. +The `copy()` command will still be re-executed, but the files for the layer will be reused from the files cache, no need to upload them from your computer again. + +To invalidate the cache for all subsequent instructions in the template **AND** the layer files cache, use the `forceUpload`/`force_upload` parameter. + + + +```typescript +template.copy("config.json", "/app/config.json", { forceUpload: true }); +``` + +```python +template.copy("config.json", "/app/config.json", force_upload=True) +``` + + + +## Use Case for Caching +You can leverage caching to create templates with multiple variants (e.g., different RAM or CPU) while reusing the common layers. +When building the template, just change the template alias to a specific RAM/CPU configuration (e.g., `my-template-2cpu-2gb`, `my-template-1cpu-4gb`), keep the rest of the template definition the same, and the build process will reuse the cached layers. + +## Optimize Build Times +To optimize build times, place frequently changing commands (e.g., copying source code) towards the end of your template definition. This way, earlier layers can be cached and reused more often. diff --git a/template/customization/defining-template.mdx b/template/customization/defining-template.mdx index 2a6c6b3..46908ba 100644 --- a/template/customization/defining-template.mdx +++ b/template/customization/defining-template.mdx @@ -74,9 +74,6 @@ template.copy([ { src: "package.json", dest: "/app/package.json" }, ]); -// Force upload (bypass cache) -template.copy("config.json", "/app/config.json", { forceUpload: true }); - // Copy with user and mode options template.copy("config.json", "/app/config.json", { user: "appuser", @@ -94,8 +91,8 @@ template.copy([ {"src": "package.json", "dest": "/app/package.json"}, ]) -# Force upload (bypass cache) -template.copy("config.json", "/app/config.json", force_upload=True) +# Copy with user and mode options +template.copy("config.json", "/app/config.json", user="appuser", mode=0o644) ``` @@ -239,24 +236,6 @@ template.set_envs({ -### Invalidating caches - -Force rebuild from the next instruction: - - - -```typescript -template.skipCache() -``` - -```python -template.skip_cache() -``` - - - -This will invalidate the cache for all subsequent instructions in the template. - ### Running commands Execute shell commands during template build: diff --git a/template/how-it-works.mdx b/template/how-it-works.mdx index b62dbe9..0f0d941 100644 --- a/template/how-it-works.mdx +++ b/template/how-it-works.mdx @@ -25,23 +25,4 @@ We call this sandbox snapshot a _sandbox template_. ## Caching -The caching concept is similar to [Docker's layer caching](https://docs.docker.com/build/cache/). For each layer command (`.copy()`, `.runCmd()`, `.setEnvs()`, etc.), we create a new layer on top of the existing. -Each layer is cached based on the command and its inputs (e.g., files copied, command executed, environment variables set). -If a layer command is unchanged and its inputs are the same as in any previous build, we reuse the cached layer instead of rebuilding it. - -This significantly speeds up the build process, especially for large templates with many layers. -The cache is scoped to the team, so even if you have multiple templates, they can share the same cache if they have identical layers. - -### Files Caching -When using the `.copy()` command, we cache the files based on their content. If the files haven't changed since the last build, we reuse them from the files cache. - -We differ from Docker here. Because we build the template on our infrastructure, we use improved caching on files level. -Even if you invalidate the layer before `.copy()` (e.g., by changing ENV variables), we'll reuse the already uploaded files. -The `copy()` command will still be re-executed, but the files for the layer will be reused from the files cache, no need to upload them from your computer again. - -### Use Case for Caching -You can leverage caching to create templates with multiple variants (e.g., different RAM or CPU) while reusing the common layers. -When building the template, just change the template alias to a specific RAM/CPU configuration (e.g., `my-template-2cpu-2gb`, `my-template-1cpu-4gb`), keep the rest of the template definition the same, and the build process will reuse the cached layers. - -### Optimize Build Times -To optimize build times, place frequently changing commands (e.g., copying source code) towards the end of your template definition. This way, earlier layers can be cached and reused more often. +To learn more about caching, please refer to the [Caching](/template/caching) section. From 251526ba518002119bb531e236b6619463a9e742 Mon Sep 17 00:00:00 2001 From: Jakub Dobry Date: Fri, 26 Sep 2025 15:39:47 +0200 Subject: [PATCH 2/2] update examples --- template/caching.mdx | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/template/caching.mdx b/template/caching.mdx index aec5b99..6db4e8a 100644 --- a/template/caching.mdx +++ b/template/caching.mdx @@ -19,12 +19,20 @@ Force rebuild from the next instruction, use the method: -```typescript -template.skipCache() +```typescript highlight={3} +const template = Template() + .fromBaseImage() + .skipCache() + .runCmd("echo 'Hello, World!'") ``` -```python -template.skip_cache() +```python highlight={4} +template = ( + Template() + .from_base_image() + .skip_cache() + .run_cmd("echo 'Hello, World!'") +) ``` @@ -66,12 +74,18 @@ To invalidate the cache for all subsequent instructions in the template **AND** -```typescript -template.copy("config.json", "/app/config.json", { forceUpload: true }); +```typescript highlight={3} +const template = Template() + .fromBaseImage() + .copy("config.json", "/app/config.json", { forceUpload: true }) ``` -```python -template.copy("config.json", "/app/config.json", force_upload=True) +```python highlight={4} +template = ( + Template() + .from_base_image() + .copy("config.json", "/app/config.json", force_upload=True) +) ```