Working with the Container registry

You can store and manage Docker and OCI images in the Container registry, which uses the package namespace https://ghcr.io.

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

About Container registry support

The Container registry currently supports the following container image formats:

When installing or publishing a Docker image, the Container registry supports foreign layers, such as Windows images.

Authenticating 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. 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 the GITHUB_TOKEN.

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

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

If you're using the Container registry in actions, follow our security best practices 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

Pushing container images

This example pushes the latest version of IMAGE-NAME.

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

This example pushes the 2.5 version of the image.

$ docker push ghcr.io/OWNER/IMAGE-NAME:2.5

When you first publish a package, the default visibility is private. To change the visibility or set access permissions, see "Configuring a package's access control and visibility."

Pulling container images

Pull by digest

To ensure you're always using the same image, you can specify the exact container image version you want to pull by the digest SHA value.

  1. To find the digest SHA value, use docker inspect or docker pull and copy the SHA value after Digest:

    $ docker inspect ghcr.io/OWNER/IMAGE_NAME
  2. Remove image locally as needed.

    $ docker rmi  ghcr.io/OWNER/IMAGE_NAME:latest
  3. Pull the container image with @YOUR_SHA_VALUE after the image name.

    $ docker pull ghcr.io/OWNER/IMAGE_NAME@sha256:82jf9a84u29hiasldj289498uhois8498hjs29hkuhs

Pull by name

$ docker pull ghcr.io/OWNER/IMAGE_NAME

Pull by name and version

Docker CLI example showing an image pulled by its name and the 1.14.1 version tag:

$ docker pull ghcr.io/OWNER/IMAGE_NAME:1.14.1
  > 5e35bd43cf78: Pull complete
  > 0c48c2209aab: Pull complete
  > fd45dd1aad5a: Pull complete
  > db6eb50c2d36: Pull complete
  > Digest: sha256:ae3b135f133155b3824d8b1f62959ff8a72e9cf9e884d88db7895d8544010d8e
  > Status: Downloaded newer image for ghcr.io/orgname/image-name/release:1.14.1
  > ghcr.io/orgname/image-name/release:1.14.1

Pull by name and latest version

$ docker pull ghcr.io/OWNER/IMAGE_NAME:latest
  > latest: Pulling from user/image-name
  > Digest: sha256:b3d3e366b55f9a54599220198b3db5da8f53592acbbb7dc7e4e9878762fc5344
  > Status: Downloaded newer image for ghcr.io/user/image-name:latest
  > ghcr.io/user/image-name:latest

Building container images

This example builds the hello_docker image:

$ docker build -t hello_docker .

Tagging container images

  1. Find the ID for the Docker image you want to tag.

    $ docker images
    > REPOSITORY                                            TAG                 IMAGE ID            CREATED             SIZE
    > ghcr.io/my-org/hello_docker         latest              38f737a91f39        47 hours ago        91.7MB
    > ghcr.io/my-username/hello_docker    latest              38f737a91f39        47 hours ago        91.7MB
    > hello-world                                           latest              fce289e99eb9        16 months ago       1.84kB
  2. Tag your Docker image using the image ID and your desired image name and hosting destination.

    $ docker tag 38f737a91f39 ghcr.io/OWNER/NEW_IMAGE_NAME:latest

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.