Skip to main content

Working with the Container registry

You can store and manage Docker and OCI images in the Container registry, which uses the package namespace

GitHub Packages is available with GitHub Free, GitHub Pro, GitHub Free for organizations, GitHub Team, GitHub Enterprise Cloud, GitHub Enterprise Server 3.0 or higher, 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 the Container registry

The Container registry stores container images within your organization or personal account, and allows you to associate an image with a repository. You can choose whether to inherit permissions from a repository, or set granular permissions independently of a repository. You can also access public container images anonymously.

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

GitHub Packages only supports authentication using a personal access token (classic). For more information, see "Creating a personal access token."

You need an access token to publish, install, and delete private, internal, and public packages.

You can use a personal access token (classic) to authenticate to GitHub Packages or the GitHub API. When you create a personal access token (classic), you can assign the token different scopes depending on your needs. For more information about packages-related scopes for a personal access token (classic), see "About permissions for GitHub Packages."

To authenticate to a GitHub Packages registry within a GitHub Actions workflow, you can use:

  • GITHUB_TOKEN to publish packages associated with the workflow repository.
  • a personal access token (classic) with at least read:packages scope to install packages associated with other private repositories (which GITHUB_TOKEN can't access).

Authenticating in a GitHub Actions workflow

This registry supports granular permissions. For registries that support granular permissions, if your GitHub Actions workflow is using a personal access token to authenticate to a registry, we highly recommend you update your workflow to use the GITHUB_TOKEN. For guidance on updating your workflows that authenticate to a registry with a personal access token, see "Upgrading a workflow that accesses a registry using a personal access token."

Note: The ability for GitHub Actions workflows to delete and restore packages using the REST API is currently in public beta and subject to change.

You can use a GITHUB_TOKEN in a GitHub Actions workflow to delete or restore a packages using the REST API, if the token has admin permission to the package. Repositories that publish packages using a workflow, and repositories that you have explicitly connected to packages, are automatically granted admin permission to packages in the repository.

For more information about the GITHUB_TOKEN, see "Authentication in a workflow." For more information about the best practices when using a registry in actions, see "Security hardening for GitHub Actions."

You can also choose to give access permissions to packages independently for GitHub Codespaces and GitHub Actions. For more information, see "Ensuring Codespaces access to your package" and "Ensuring workflow access to your package."

Authenticating with a personal access token (classic)

GitHub Packages only supports authentication using a personal access token (classic). For more information, see "Creating a personal access token."

  1. Create a new personal access token (classic) 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 (classic) 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 personal access token (classic) in the user interface with this url:

    • 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 personal access token (classic). We recommend saving your token 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

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

Pushing container images

This example pushes the latest version of IMAGE_NAME.

$ docker push

This example pushes the 2.5 version of the image.

$ docker push

When you first publish a package, the default visibility is private. When a package is linked to a repository, the package visibility is dependent on the repository's visibility. To change the visibility or set access permissions, see "Configuring a package's access control and visibility." You can link a published package to a repository using the user interface or command line. For more information, see "Connecting a repository to a package."

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
  2. Remove image locally as needed.

    $ docker rmi
  3. Pull the container image with @YOUR_SHA_VALUE after the image name.

    $ docker pull

Pull by name

$ docker pull

Pull by name and version

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

$ docker pull
  > 5e35bd43cf78: Pull complete
  > 0c48c2209aab: Pull complete
  > fd45dd1aad5a: Pull complete
  > db6eb50c2d36: Pull complete
  > Digest: sha256:ae3b135f133155b3824d8b1f62959ff8a72e9cf9e884d88db7895d8544010d8e
  > Status: Downloaded newer image for

Pull by name and latest version

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

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
    >         latest              38f737a91f39        47 hours ago        91.7MB
    >    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

Labelling container images

You can use pre-defined annotation keys to add metadata including a description, a license, and a source repository to your container image. Values for supported keys will appear on the package page for the image.

For most images, you can use Docker labels to add the annotation keys to an image. For more information, see LABEL in the official Docker documentation and Pre-Defined Annotation Keys in the opencontainers/image-spec repository.

For multi-arch images, you can add a description to the image by adding the appropriate annotation key to the annotations field in the image's manifest. For more information, see "Adding a description to multi-arch images."

The following annotation keys are supported in the Container registry.

org.opencontainers.image.sourceThe URL of the repository associated with the package. For more information, see "Connecting a repository to a package."
org.opencontainers.image.descriptionA text-only description limited to 512 characters. This description will appear on the package page, below the name of the package.
org.opencontainers.image.licensesAn SPDX license identifier such as "MIT," limited to 256 characters. The license will appear on the package page, in the "Details" sidebar. For more information, see SPDX License List.

To add a key as a Docker label, we recommend using the LABEL instruction in your Dockerfile. For example, if you're the user monalisa and you own my-repo, and your image is distributed under the terms of the MIT license, you would add the following lines to your Dockerfile:

LABEL org.opencontainers.image.source=
LABEL org.opencontainers.image.description="My container image"
LABEL org.opencontainers.image.licenses=MIT

Alternatively, you can add labels to an image at buildtime with the docker build command.

$ docker build \
 --label "org.opencontainers.image.source=" \
 --label "org.opencontainers.image.description=My container image" \
 --label "org.opencontainers.image.licenses=MIT"

Adding a description to multi-arch images

A multi-arch image is an image that supports multiple architectures. It works by referencing a list of images, each supporting a different architecture, within a single manifest.

The description that appears on the package page for a multi-arch image is obtained from the annotations field in the image's manifest. Like Docker labels, annotations provide a way to associate metadata with an image, and support pre-defined annotation keys. For more information, see Annotations in the opencontainers/image-spec repository.

To provide a description for a multi-arch image, set a value for the org.opencontainers.image.description key in the annotations field of the manifest, as follows.

"annotations": {
  "org.opencontainers.image.description": "My multi-arch image"

For example, the following GitHub Actions workflow step builds and pushes a multi-arch image. The outputs parameter sets the description for the image.

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

- name: Build and push Docker image
  uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
    context: .
    file: ./Dockerfile
    platforms: ${{ matrix.platforms }}
    push: true
    outputs: type=image,name=target, multi-arch image