Skip to content
Docs

Push Images from GitHub Actions

Push images to Vercel Container Registry (VCR) from GitHub Actions without storing long-lived credentials. The vercel/vcr-action/login action exchanges the GitHub Actions OpenID Connect (OIDC) token for a short-lived Vercel access token and logs in Docker, Podman, or Buildah, so there are no secrets to rotate. You then build and push with your own commands. When the job completes, a post step logs out and revokes the token.

  • Create an OIDC policy on your Vercel team that grants read-write access to Vercel Container Registry.
  • Store your Vercel team ID (team_...) as a repository variable, for example VERCEL_TEAM_ID.
  • Give the workflow or job the id-token: write permission.

This example pushes directly from BuildKit with zstd compression, which is the recommended format for VCR images. The repository is created on the first push:

.github/workflows/push-to-vcr.yml
name: Push to VCR
 
on:
  push:
    branches: [main]
 
permissions:
  contents: read
  id-token: write
 
jobs:
  push:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
 
      - uses: docker/setup-buildx-action@v3
 
      - name: Log in to VCR
        uses: vercel/vcr-action/login@v1
        with:
          team: ${{ vars.VERCEL_TEAM_ID }}
 
      - name: Build and push
        uses: docker/build-push-action@v6
        with:
          context: .
          platforms: linux/amd64
          provenance: false
          tags: vcr.vercel.com/team-slug/project-name/my-app:latest
          outputs: type=image,push=true,oci-mediatypes=true,compression=zstd,compression-level=3,force-compression=true

You can also push with plain docker build and docker push after the login step. See the action reference for all inputs and outputs.

The engines input selects which container tools to authenticate. It accepts docker (the default), podman, and buildah, in any combination:

.github/workflows/push-to-vcr.yml
- name: Log in to VCR
  uses: vercel/vcr-action/login@v1
  with:
    team: ${{ vars.VERCEL_TEAM_ID }}
    engines: podman
 
- name: Build and push
  run: |
    podman build --platform linux/amd64 -t "$IMAGE" .
    podman push "$IMAGE"
  env:
    IMAGE: vcr.vercel.com/team-slug/project-name/my-app:latest
  1. The action requests a GitHub OIDC token from the runner and exchanges it with Vercel for a short-lived access token scoped to your team. The exchange only succeeds when your team has an OIDC policy that matches the repository and workflow.
  2. The action logs in to vcr.vercel.com with the token. The username is your team ID.
  3. When the job completes, a post step logs out and revokes the token, even if a later step fails.
Last updated September 4, 2026

Was this helpful?

supported.