Migrating to the Container registry from the Docker registry

If you've used the GitHub Packages Docker registry to store Docker images, you can migrate your images 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, and GitHub AE.


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 the Container registry since these accounts are billed by repository. For more information, see "GitHub's products."

In this article

Key differences between the Container registry and the Docker registry

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

The Container registry supersedes the existing GitHub 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 granular permissions and visibility independently of repository permissions and visibility.
  • Access public container images anonymously.
Docker registryContainer registry
Hosting locationsYou can host multiple Docker images in one repository.You can host multiple container images in one organization or user account.
PermissionsEach image inherits the permissions of the repository where the image is hosted.

For example, anyone with read permissions for a repository can install a package as a dependency in a project, and anyone with write permissions can publish a new package version.
For each container image, you can choose the access level that others have. The permissions for container image access are separate from your organization and repository permissions.
VisibilityYou can publish packages in a public repository (public packages) to share with all of GitHub, or in a private repository (private packages) to share with collaborators or an organization.You can set the visibility of each of your container images. A private container image is only visible to people and teams who are given access within your organization. A public container image is visible to anyone.
Anonymous accessN/AYou can access public container images anonymously.
Foreign layer supportDoesn't support foreign layers, such as Windows images.Supports foreign layers, such as Windows images.

Billing changes

During the Container registry beta, both the new Container registry and the existing GitHub Packages Docker registry are free of charge. For more information about the GitHub Packages Docker registry, see "Working with the Docker registry."

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
Container registryghcr.io/OWNER/IMAGE_NAME

Authenticating to the Container registry

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

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.

PATs can grant broad access to your account. You should select only the necessary read:packages, write:packages, or delete:packages scope when creating a PAT to authenticate to the Container registry.

To authenticate to the Container registry within a GitHub Actions workflow, use the GITHUB_TOKEN for the best security and experience.

For guidance on updating your workflows that authenticate to ghcr.io with a personal access token, see "Upgrading a workflow that accesses ghcr.io."

The Container registry now supports GITHUB_TOKEN for easy and secure authentication in your workflows. If your workflow is using a personal access token (PAT) to authenticate to ghcr.io, then we highly recommend you update your workflow to use GITHUB_TOKEN.

For more information about GITHUB_TOKEN, see "Authentication in a workflow."

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: By default, when you select the write:packages scope for your personal access token (PAT) in the user interface, the repo scope will also be selected. The repo scope offers unnecessary and broad access, which we recommend you avoid using for GitHub Actions workflows in particular. For more information, see "Security hardening for GitHub Actions." As a workaround, you can select just the write:packages scope for your PAT in the user interface with this url: https://github.com/settings/tokens/new?scopes=write:packages.

    • 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 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 the Container registry, you must enable the feature for your account. For more information, see "Enabling improved container support with the Container registry."

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. The 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.