Skip to main content
Start with the Runloop Quickstart to use the examples below.

Build Context

Many Dockerfiles use COPY and ADD to include files and directories from the local context into a container. You can get exactly the same behavior when building Blueprints in Runloop by using the object store and build context features. A build context is useful when you want to:
  • Include application source code in your Blueprint
  • Bundle multiple files and directories efficiently
  • Use Docker’s COPY and ADD instructions in your Dockerfile
Build contexts are stored as temporary Storage Objects and can be automatically cleaned up by setting a time-to-live (TTL). Make sure to set a TTL that is long enough for your blueprint build to complete.

Example: Creating a Blueprint with Local Application Files

This example shows how to upload a local directory and use it as a build context in your Blueprint’s Dockerfile:
from datetime import timedelta

# Upload a local directory as a build context
build_context_obj = await runloop.storage_objects.upload_from_dir(
    "./my-app",  # Local directory path
    ttl=timedelta(hours=24),  # Optional: set expiration
)

# Create blueprint with build context
blueprint = await runloop.blueprint.create(
    name="my-app-blueprint",
    dockerfile="""\
FROM ubuntu:22.04
WORKDIR /app

# Copy files from build context
COPY . .

# Install dependencies
RUN npm install

# Set up any additional configuration
RUN chmod +x ./start.sh
""",
    build_context=build_context_obj.as_build_context(),
)

print(f"Blueprint created: {blueprint.id}")
The COPY instruction in your Dockerfile will copy files from the uploaded build context, not from your local filesystem. Make sure your local directory contains all the files your Dockerfile needs before uploading.
If your local directory contains a .dockerignore file, those patterns will be respected during the upload. This helps reduce the size of your build context by excluding unnecessary files like node_modules or .git.

Object Mounts

For larger files, datasets, or binary assets that you want to include in your Blueprint, use object mounts. Objects are stored in Runloop’s storage and can be reused across multiple Blueprints.
# Upload a file as a storage object
storage_object = await runloop.storage_objects.upload_from_file(
    "./model-weights.bin",
    name="model-weights"
)

# Create blueprint with object mount
blueprint = await runloop.blueprint.create(
    name="ml-blueprint",
    object_mounts=[{
        "object_id": storage_object.id,
        "object_path": "/home/user/model-weights.bin"
    }]
)
If your storage object has a TTL set, ensure it won’t expire before your blueprint build completes. For persistent assets, consider creating objects without a TTL.
For more details on creating and managing storage objects, see the Storage Objects documentation and Object Mounts guide.

Code Mounts

To add a CodeMount to your Blueprint:
blueprint = await runloop.blueprint.create(
  name="fe-bot",
  code_mounts=[{
    "repo_name": "runloop-fe",
    "repo_owner": "runloop",
    "token": os.environ.get("GH_TOKEN")
  }]
)
print(f"Blueprint created with ID: {blueprint.id}")
This creates a Blueprint named “fe-bot” that includes the “runloop-fe” repository. The token field is used for private repository authentication - include a GitHub Personal Access Token (PAT) with appropriate permissions.

File Mounts

File mounts are only recommended for very small files like configuration snippets. For larger files or directories, use build context or object mounts instead.
The file_mounts parameter lets you add individual files to your Blueprint. The key is the path to the file in the devbox and the value is the content of the file. By default, blueprints are constructed by user and /home/user/ is where files are allowed to be mounted.
blueprint = await runloop.blueprint.create(
  name="config-blueprint",
  file_mounts={
    "/home/user/hello.txt": "Hello, world!"
  }
)

Mounting Files to Root

If you want to mount files to root, you will need to specify building the blueprint as root via launch_parameters:
blueprint = await runloop.blueprint.create(
  name="root-config-blueprint",
  file_mounts={
    "/etc/myconfig.txt": "config_value=123"
  },
  launch_parameters={
    "user_parameters": {
      "username": "root",
      "uid": 0
    }
  }
)

Next Steps