Migrating to GitHub Container Registry for Docker images

If you've used the GitHub Packages Docker registry to store Docker images, you can migrate to the new container registry.

GitHub Packages is available with GitHub Free, GitHub Pro, GitHub Free for organizations, GitHub Team, GitHub Enterprise Cloud, GitHub Enterprise Server 2.22, and GitHub One.


GitHub Packages is not available for private repositories owned by accounts using legacy per-repository plans. Also, accounts using legacy per-repository plans cannot access GitHub Container Registry since these accounts are billed by repository. For more information, see "GitHub's products."

In this article

Key differences between GitHub Container Registry and the Docker package registry

Note: GitHub Container Registry is currently in public beta and subject to change. During the beta, storage and bandwidth are free. To use GitHub Container Registry, you must enable the feature preview. For more information, see "About GitHub Container Registry" and "Enabling improved container support."

The GitHub Container Registry supersedes the existing Packages Docker registry and is optimized to support some of the unique needs of containers.

With the container registry you can:

  • Store container images within your organization and user account, rather than a repository.
  • Set fine-grained permissions and visibility independent of repository permissions and visibility.
  • Access public container images anonymously.

For more information, see "About GitHub Container Registry."

Billing changes

During the GitHub Container Registry beta, both the new container registry and existing GitHub Packages Docker registry will be free. For more information about the GitHub Packages Docker registry, see "Configuring Docker for use with GitHub Packages."

After the beta, the same billing and storage rates that other GitHub Packages registries use will apply to the container registry. For more information, see "About billing for GitHub Packages."

Domain changes

The domain for the container registry is ghcr.io.

RegistryExample URL
GitHub Packages Docker registrydocker.pkg.github.com/OWNER/REPOSITORY/IMAGE_NAME
GitHub Container Registryghcr.io/OWNER/IMAGE_NAME

Authenticating with the container registry

Note: Before you can use GitHub Container Registry, you must enable the feature for your account. For more information, see "Enabling improved container support."

You will need to authenticate to the container registry with the base URL ghcr.io. We recommend creating a new access token for using the container registry.

If you want to authenticate to GitHub Container Registry in a GitHub Actions workflow, then you must use a personal access token (PAT). The GITHUB_TOKEN does not currently have the required permissions. During the GitHub Container Registry beta, the only supported form of authentication is the PAT.

PATs can grant broad access to your account. We recommend selecting only the necessary read, write, or delete package scope when creating a PAT to authenticate to the container registry. Avoid including the repo scope in a PAT used by a GitHub Actions workflow because it gives unnecessary additional access.

If you'd like to use the container registry in actions during the beta, follow our security best practices for PAT use at "Security hardening for GitHub Actions."

  1. Create a new personal access token (PAT) with the appropriate scopes for the tasks you want to accomplish. If your organization requires SSO, you must enable SSO for your new token.

    Note: If you select the write:packages scope, deselect the repo scope when creating the PAT. Adding a PAT with the repo scope as a secret in your repository allows the credential to be accessible to all collaborators in the repository. This gives unnecessary additional access when a PAT with the repo scope is used within an action. For more information on security best practices for actions, see "Security hardening for GitHub Actions."

    • Select the read:packages scope to download container images and read their metadata.
    • Select the write:packages scope to download and upload container images and read and write their metadata.
    • Select the delete:packages scope to delete container images.

    For more information, see "Creating a personal access token for the command line."

  2. Save your PAT. We recommend saving your PAT as an environment variable.

    $ export CR_PAT=YOUR_TOKEN
  3. Using the CLI for your container type, sign in to the GitHub Container Registry service at ghcr.io.

    $ echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
    > Login Succeeded

Migrating a Docker image using the Docker CLI

To move Docker images that you host on GitHub Packages Docker registry, you must republish the images to container registry. We recommend republishing your existing Docker images using the command line on your local machine.

  1. Sign in to the Docker registry using a temporary PAT with at least the read:packages scope. This PAT will only be used to sign in to the Docker registry to pull down images and can be deleted afterward.

    $ echo $READ_PACKAGES_TOKEN | docker login docker.pkg.github.com -u USERNAME --password-stdin
  2. Pull down the image you'd like to migrate, replacing OWNER with the name of the user or organization account that owns the repository, REPOSITORY with the name of the repository containing your project, IMAGE_NAME with name of the package or image, VERSION with tag for the image you want to install. For example, docker pull docker.pkg.github.com/octo-org/octoshift/octoshift:latest pulls the latest tag of the octoshift/octoshift image in the octo-org organization.

    $ docker pull docker.pkg.github.com/OWNER/REPOSITORY/IMAGE_NAME:VERSION
  3. Re-tag the image with the new domain and a new image name. For more information, see "Docker tag" in the Docker documentation. Use the same URL that you used in the previous step for the SOURCE URL. Replace the TARGET_OWNER with the user or organization that you are migrating the container image to and replace the TARGET_IMAGE_NAME with the new container registry image name.

    $ docker tag docker.pkg.github.com/SOURCE_OWNER/SOURCE_REPOSITORY/SOURCE_IMAGE_NAME:VERSION ghcr.io/TARGET_OWNER/TARGET_IMAGE_NAME:VERSION
  4. Sign in to the new container registry. We recommend creating a new PAT limited to the read:packages and write:packages scopes since you no longer need the repo scope and your previous PAT may not have the write:packages scope.

    $ echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
  5. Push your re-tagged image to the container registry.

    $ docker push ghcr.io/OWNER/IMAGE_NAME:VERSION

Updating your GitHub Actions workflow

Note: Before you can use GitHub Container Registry, you must enable the feature for your account. For more information, see "Enabling improved container support."

If you have a GitHub Actions workflow that uses a Docker image from the GitHub Packages Docker registry, you may want to update your workflow to the container registry to allow for anonymous access for public container images, finer-grain access permissions, and better storage and bandwidth compatibility for containers.

  1. Migrate your Docker images to the new container registry at ghcr.io. For an example, see "Migrating a Docker image using the Docker CLI."

  2. In your GitHub Actions workflow file, update the package url from https://docker.pkg.github.com to ghcr.io.

  3. Add your new container registry authentication personal access token (PAT) as a GitHub Actions secret. GitHub Container Registry does not support using GITHUB_TOKEN for your PAT so you must use a different custom variable, such as CR_PAT. For more information, see "Creating and storing encrypted secrets."

  4. In your GitHub Actions workflow file, update the authentication PAT by replacing your Docker registry PAT (${{ secrets.GITHUB_TOKEN }}) with a new variable for your container registry PAT, such as ${{ secrets.CR_PAT }}.

Example of updated workflow

If part of your workflow accessed a Docker image hosted by the Docker registry like this:

echo ${{ secrets.GITHUB_TOKEN }} | docker login https://docker.pkg.github.com -u $GITHUB_ACTOR --password-stdin
docker pull docker.pkg.github.com/github/octoshift/octoshift:latest
docker build . --tag docker.pkg.github.com/github/octoshift/octoshift:$GITHUB_SHA --cache-from docker.pkg.github.com/github/octoshift/octoshift:latest
docker push docker.pkg.github.com/github/octoshift/octoshift:$GITHUB_SHA

Then you'll need to update your workflow with the new container registry URL and PAT like this:

# new login with new container registry url and PAT
echo ${{ secrets.CR_PAT }} | docker login ghcr.io -u $GITHUB_ACTOR --password-stdin
# new container registry urls added
docker pull ghcr.io/github/octoshift:latest
docker build . --tag ghcr.io/github/octoshift:$GITHUB_SHA --cache-from ghcr.io/github/octoshift:latest
docker push ghcr.io/github/octoshift:$GITHUB_SHA

Did this doc help you?

Privacy policy

Help us make these docs great!

All GitHub docs are open source. See something that's wrong or unclear? Submit a pull request.

Make a contribution

Or, learn how to contribute.