---
title: Push Images from GitHub Actions
product: vercel
url: /docs/container-registry/github-actions
canonical_url: "https://vercel.com/docs/container-registry/github-actions"
last_updated: 2018-10-20
type: how-to
prerequisites:
  - /docs/container-registry
related:
  - /docs/sandbox/concepts/images
  - /docs/functions/container-images
  - /docs/container-registry/cli-reference
summary: Authenticate GitHub Actions with Vercel Container Registry using OIDC, then build and push images with your container tool.
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

# 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`](https://github.com/vercel/vcr-action/tree/main/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.

## Prerequisites

- [Create an OIDC policy](/d?to=%2F%5Bteam%5D%2F%7E%2Fsettings%2Fbuild-and-deployment%3FaddOidcPolicy%3Dvcr\&title=Add+a+VCR+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.

## Log in and push

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:

```yaml filename=".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](https://github.com/vercel/vcr-action/tree/main/login#readme) for all inputs and outputs.

## Log in with Podman or Buildah

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

```yaml filename=".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
```

## How it works

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.

## Next steps

- [Use the image with Vercel Sandbox](/docs/sandbox/concepts/images#custom-images)
- [Use the image with Vercel Functions](/docs/functions/container-images#usage)
- [Manage repositories with the Vercel CLI](/docs/container-registry/cli-reference)


---

[View full sitemap](/docs/sitemap)
