On Runtime, the credential is sealed to the servers as soon as it arrives. No call returns it, and the API that stored it cannot read it back. A build opens it only to pull, inside its own build machine. Neither your sandboxes nor your agent ever hold the registry token. Docker Hub, GitHub, Google, Amazon ECR, and any other registry that takes a user name and token work (private registries, checked 26 October 2026).
Store the credential
Each CLI form reads the secret from standard input. The secret never appears in your shell history or on a command line.
Terminalecho "$GHCR_TOKEN" | runtime images registry set ghcr.io --username my-userecho "$AWS_SECRET_ACCESS_KEY" | runtime images registry set 123456789012.dkr.ecr.us-east-1.amazonaws.com --access-key-id AKIA...runtime images registry lsFrom code, keep the token in your own secret store and pass it through an environment variable:
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.registries.set({ registry: "ghcr.io", username: "my-user", password: process.env.GHCR_TOKEN ?? "",});console.log(await runtime.images.registries.list()); // never the tokenPythonimport osfrom withruntime import Runtimeruntime = Runtime()runtime.images.registries.set("ghcr.io", username="my-user", password=os.environ.get("GHCR_TOKEN", ""))print(runtime.images.registries.list())What each registry needs
| Registry | Give |
|---|---|
Docker Hub (docker.io) |
Your user name and an access token |
GitHub (ghcr.io) |
Your user name and a token that can read packages |
Google (gcr.io, *-docker.pkg.dev) |
_json_key and the service account key's JSON, or oauth2accesstoken and an access token |
Amazon ECR (<account>.dkr.ecr.<region>.amazonaws.com) |
An access key ID and secret that allow ecr:GetAuthorizationToken and pull. Each build requests a fresh token from ECR |
| Any other | A user name and a token or password |
An account can hold up to 20 registry credentials. To remove one, call
runtime.images.registries.delete(registry).
Build from the private image
A sandbox starts from a Runtime image. So the private image goes through one build first. Use it as is:
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({ name: "app", image: "ghcr.io/acme/app:1.4.2" });await using sbx = await runtime.sandboxes.create({ image: "app" });console.log((await sbx.exec("cat /etc/os-release")).stdout);Pythonfrom withruntime import Runtimeruntime = Runtime()runtime.images.build(name="app", image="ghcr.io/acme/app:1.4.2")with runtime.sandboxes.create(image="app") as sbx: print(sbx.exec("cat /etc/os-release").stdout)Terminalruntime images build --from ghcr.io/acme/app:1.4.2 --name appruntime sandboxes create --image appThe same stored credential covers FROM in a
Dockerfile, COPY --from=<image>,
and a recipe's base. So a private base
image with a few packages added on top takes one build:
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({ name: "app-tools", recipe: { base: "ghcr.io/acme/app:1.4.2", apt: ["jq"], pip: ["pytest"] },});A program in the sandbox is found on the image's own PATH. So python in an
image built from python:3.12-slim runs as it does there.
Keep it current
Each build of a name becomes its next version. It takes latest, or the tags
you give. When the registry publishes 1.4.3, build again with the same name.
Sandboxes that ask for app get the new version. Sandboxes already running keep
theirs. To pin a version, use app@2 or a tag such as app:prod
(names, versions and tags).
Mistakes to avoid
- A GitHub token without package read access. The pull is refused. Make a token that can read packages.
- Putting the token in a Dockerfile or build argument. It would be in the image. Store it as a registry credential, which a build opens only to pull.
- An ECR login token instead of an access key. Give an access key ID and
secret that may call
ecr:GetAuthorizationToken. Each build requests a fresh token from ECR itself. - Giving the sandbox registry access to pull at run time. It does not need it, because the image is already built. If code in the sandbox must call a private API, use a secret it never sees scoped to that host.
Building is free. Without credit, a build counts toward the free usage. A stored image costs $0.08 per decimal GB per 30-day month, based on its accounted storage. An account without credit keeps its first three images free (pricing). For containers that the sandbox runs itself, see Docker in a sandbox.
A stored image is charged for its whole file (image storage pricing).
Facts on this page were checked on 26 October 2026.