Skip to content
Docs

How to use Vercel Container Registry

Push, store, and pull OCI container images with Vercel Container Registry, then deploy them to Vercel Functions and Vercel Sandbox.

Ben SabicContent Engineer

Getting a container image from your laptop to a running function usually means setting up a separate registry, configuring credentials, and configuring your build pipeline to push to it. Vercel Container Registry (VCR) removes that step by giving every Vercel project a built-in, OCI-compatible registry at vcr.vercel.com. You push images with the same docker tooling you already use. Vercel Functions and Vercel Sandbox pull them directly, and VCR optimizes images automatically for Fluid compute.

In this guide, you'll learn how to authenticate Docker with Vercel Container Registry, build and push an OCI image to your project's registry, pull it for local verification or CI, and reference it from a Vercel Function or Vercel Sandbox, all within VCR's size, format, and plan limits.

Copy link to headingPrerequisites

Before you begin, make sure you have:

  • A Vercel account with access to the project you want to push to
  • Docker installed and running locally, and optionally Docker Buildx (multi-platform)
  • The Vercel CLI installed and authenticated with vercel login
  • A local project linked to your Vercel project with vercel link

Copy link to headingHow it works

Every Vercel project has its own namespace in VCR. A full image reference has four parts: the registry host, your team slug, your project slug, and the repository name with a tag or digest.

vcr.vercel.com/team-slug/project-slug/my-repository:latest

VCR speaks the Docker Registry HTTP API v2 and stores images in OCI format, so docker login, docker push, docker pull, and docker tag work without extra tooling. When you push an image, VCR builds an optimized snapshot in the background so it boots faster inside Vercel Functions and Vercel Sandbox on Fluid compute.

Copy link to headingSteps

From the root of the project you want to push images for, link the local directory to your Vercel project and download its environment variables:

vercel link
vercel env pull .env.local
source .env.local

vercel env pull writes VERCEL_OIDC_TOKEN into .env.local, which you'll use as the Docker password. The token is scoped to the linked project and expires after 12 hours, so refresh it with vercel env pull before the 12-hour window closes.

Copy link to heading2. Authenticate Docker with VCR

Log Docker in to vcr.vercel.com using the OIDC token as the password and oidc as the username:

printf '%s' "$VERCEL_OIDC_TOKEN" | docker login vcr.vercel.com \
--username oidc \
--password-stdin

Docker responds with Login Succeeded when the credentials are accepted.

If OIDC isn't available in your environment (e.g., in a CI system that doesn't run vercel env pull), create a token on the Account Tokens page and log in with your team ID as the username:

printf '%s' "$VERCEL_TOKEN" | docker login vcr.vercel.com \
--username "$VERCEL_TEAM_ID" \
--password-stdin

Copy link to heading3. Build and tag the image locally

Tag the image with the full VCR path so docker push knows where to send it. Replace team-slug and project-slug with the values for your linked project.

docker build -t vcr.vercel.com/team-slug/project-slug/my-repository:latest

If the repository doesn't exist yet, VCR creates it the first time you push, provided you have access to the project.

Copy link to heading4. Push the image to VCR

To push the image, use docker push with the tag you built:

docker push vcr.vercel.com/team-slug/project-slug/my-repository:latest

For production images, build with Buildx and zstd compression. This produces smaller layers and faster snapshot boots on Fluid compute, and lets you build for both linux/amd64 and linux/arm64 in one step:

docker buildx build \
--platform linux/amd64,linux/arm64 \
--output "type=image,name=vcr.vercel.com/team-slug/project-slug/my-repository:latest,push=true,oci-mediatypes=true,compression=zstd,compression-level=3,force-compression=true"

Copy link to heading5. Pull the image for verification

To confirm the push landed, pull the image back to your machine or into a CI job using the same full path:

docker pull vcr.vercel.com/team-slug/project-slug/my-repository:latest

You can also browse tags and digests from the Images tab in your project dashboard.

Copy link to heading6. Reference the image from Vercel Functions

To run the image as a Vercel Function, add a Dockerfile.vercel (or Containerfile.vercel) at the root of your project. Vercel detects it during the build, pushes the image to VCR, and routes traffic to the resulting function.

FROM node:26-alpine
RUN npm i -g srvx
WORKDIR /app
COPY server.ts .
# srvx listens on $PORT by default
CMD ["srvx", "--prod"]

Deploy with vercel deploy or by pushing to a connected Git branch. Container-based functions serve HTTP on port 80 by default; you can override this by setting the PORT environment variable in your project settings. They follow the same Active CPU pricing and limits as any other Vercel Function. Note that Secure Compute and Static IPs are not yet supported with custom container images.

Copy link to heading7. Reference the image from Vercel Sandbox

Custom images for Vercel Sandbox are available in public beta. To boot a sandbox from a custom VCR image, pass the repository and tag to Sandbox.create():

import { Sandbox } from "@vercel/sandbox";
const sandbox = await Sandbox.create({
image: "my-repository:latest",
});

The sandbox boots from your image's filesystem rather than the built-in runtime, so the system libraries and toolchains specified in your Dockerfile are already in place. Note that Sandbox requires a linux/amd64 manifest and only boots the image after VCR finishes preparing an optimized build. If Sandbox.create() returns image_not_ready, retry once preparation completes. You can check the readiness state on the repository details page. Sandbox also does not run your image's ENTRYPOINT or CMD; start processes with sandbox.runCommand() after creation. If your Dockerfile defines a WORKDIR, commands start there; otherwise they start from /.

Copy link to headingLimits and best practices

Keep these limits in mind when planning your images.

Copy link to headingSize limits

LimitMaximumNotes
Compressed layer size500 MBPer layer
Total image size15 GBCalculated from compressed layers plus the config blob
Manifest body4 MB—
Image config blob1 MB—

Copy link to headingCompatibility

  • Compression: VCR accepts gzip or zstd compression only. Uncompressed OCI layers are rejected.
  • Formats: OCI image manifests, OCI image indexes, Docker schema 2 image manifests, and Docker manifest lists
  • Single-platform manifests must declare os and architecture in the image config
  • Vercel Sandbox requires a linux/amd64 manifest to boot the image

Copy link to headingPlan limits and pricing

LimitHobbyProEnterprise
Repositories per project101,0005,000
Images per repository5010,00050,000
Tags per repository1,00010,00050,000

Storage costs $0.10 per GB across all plans. See limits and pricing for current details.

Additional practices to keep in mind:

  • Build with Docker Buildx and zstd compression for faster boots on Fluid compute
  • Use immutable tags (like a commit SHA) for production images, and reserve latest for local iteration
  • Push from your Vercel build environment when possible; it's authenticated for the current project automatically

Copy link to headingResources and next steps

More Vercel Container Registry guides