|
| 1 | +--- |
| 2 | +title: Working with the Container registry |
| 3 | +intro: 'You can store and manage Docker and OCI images in the {% data variables.product.prodname_container_registry %}.' |
| 4 | +product: '{% data reusables.gated-features.packages %}' |
| 5 | +redirect_from: |
| 6 | + - /packages/managing-container-images-with-github-container-registry/pushing-and-pulling-docker-images |
| 7 | + - /packages/guides/container-guides-for-github-packages/pushing-and-pulling-docker-images |
| 8 | + - /packages/guides/pushing-and-pulling-docker-images |
| 9 | + - /packages/getting-started-with-github-container-registry/about-github-container-registry |
| 10 | + - /packages/managing-container-images-with-github-container-registry |
| 11 | + - /packages/working-with-a-github-packages-registry/enabling-improved-container-support-with-the-container-registry |
| 12 | + - /packages/getting-started-with-github-container-registry/enabling-improved-container-support |
| 13 | + - /packages/guides/container-guides-for-github-packages/enabling-improved-container-support |
| 14 | + - /packages/guides/enabling-improved-container-support |
| 15 | +versions: |
| 16 | + fpt: '*' |
| 17 | + ghec: '*' |
| 18 | + ghes: '*' |
| 19 | +shortTitle: Container registry |
| 20 | +category: |
| 21 | + - Work with a package registry |
| 22 | +--- |
| 23 | + |
| 24 | +{% data reusables.package_registry.container-registry-ghes-beta %} |
| 25 | + |
| 26 | +## About the {% data variables.product.prodname_container_registry %} |
| 27 | + |
| 28 | +{% data reusables.package_registry.container-registry-benefits %} |
| 29 | + |
| 30 | +{% ifversion ghes %} |
| 31 | + |
| 32 | +To use the {% data variables.product.prodname_container_registry %} on {% data variables.product.prodname_ghe_server %}, your site administrator must first configure {% data variables.product.prodname_registry %} for your instance **and** enable subdomain isolation. For more information, see [AUTOTITLE](/admin/packages/getting-started-with-github-packages-for-your-enterprise) and [AUTOTITLE](/admin/configuration/configuring-network-settings/enabling-subdomain-isolation). |
| 33 | + |
| 34 | +{% endif %} |
| 35 | + |
| 36 | +{% ifversion ghec %} |
| 37 | + |
| 38 | +## URL for the {% data variables.product.prodname_container_registry %} |
| 39 | + |
| 40 | +If you access {% data variables.product.github %} at {% data variables.product.prodname_dotcom_the_website %}, you will publish packages to {% data reusables.package_registry.container-registry-hostname %}. Examples in this article use this URL. |
| 41 | + |
| 42 | +If you access {% data variables.product.github %} at another domain, such as `octocorp.ghe.com`, replace "{% data reusables.package_registry.container-registry-hostname %}" with `https://containers.SUBDOMAIN.ghe.com`, where `SUBDOMAIN` is your enterprise's unique subdomain. |
| 43 | + |
| 44 | +{% endif %} |
| 45 | + |
| 46 | +## About {% data variables.product.prodname_container_registry %} support |
| 47 | + |
| 48 | +The {% data variables.product.prodname_container_registry %} currently supports the following container image formats: |
| 49 | + |
| 50 | +* [Docker Image Manifest V2, Schema 2](https://docs.docker.com/registry/spec/manifest-v2-2/) |
| 51 | +* [Open Container Initiative (OCI) Specifications](https://github.com/opencontainers/image-spec) |
| 52 | + |
| 53 | +When installing or publishing a Docker image, the {% data variables.product.prodname_container_registry %} supports foreign layers, such as Windows images. |
| 54 | + |
| 55 | +## Authenticating to the {% data variables.product.prodname_container_registry %} |
| 56 | + |
| 57 | +{% data reusables.package_registry.authenticate-packages %} |
| 58 | + |
| 59 | +### Authenticating in a {% data variables.product.prodname_actions %} workflow |
| 60 | + |
| 61 | +This registry supports granular permissions. {% data reusables.package_registry.authenticate_with_pat_for_v2_registry %} |
| 62 | + |
| 63 | +{% data reusables.package_registry.v2-actions-codespaces %} |
| 64 | + |
| 65 | +### Authenticating with a {% data variables.product.pat_v1 %} |
| 66 | + |
| 67 | +{% ifversion ghes %}Ensure that you replace `HOSTNAME` with {% data variables.location.product_location_enterprise %} hostname or IP address in the examples below.{% endif %} |
| 68 | + |
| 69 | +{% data reusables.package_registry.authenticate-to-container-registry-steps %} |
| 70 | + |
| 71 | +## Pushing container images |
| 72 | + |
| 73 | +This example pushes the latest version of `IMAGE_NAME`. |
| 74 | + |
| 75 | +```shell |
| 76 | +docker push {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME:latest |
| 77 | +``` |
| 78 | + |
| 79 | +Replace `NAMESPACE` with the name of the personal account or organization to which you want the image to be scoped. |
| 80 | + |
| 81 | +This example pushes the `2.5` version of the image. |
| 82 | + |
| 83 | +```shell |
| 84 | +docker push {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME:2.5 |
| 85 | +``` |
| 86 | + |
| 87 | +{% data reusables.package_registry.publishing-user-scoped-packages %} You can link a published package to a repository using the user interface or command line. For more information, see [AUTOTITLE](/packages/learn-github-packages/connecting-a-repository-to-a-package). |
| 88 | + |
| 89 | +When you push a container image from the command line, the image is not linked to a repository by default. This is the case even if you tag the image with a namespace that matches the name of the repository, such as `{% ifversion fpt or ghec %}ghcr.io{% elsif ghes %}{% data reusables.package_registry.container-registry-example-hostname %}{% endif %}/octocat/my-repo:latest`. |
| 90 | + |
| 91 | +The easiest way to connect a repository to a container package is to publish the package from a workflow using `${% raw %}{{secrets.GITHUB_TOKEN}}{% endraw %}`, as the repository that contains the workflow is linked automatically. Note that the `GITHUB_TOKEN` will not have permission to push the package if you have previously pushed a package to the same namespace, but have not connected the package to the repository. |
| 92 | + |
| 93 | +To connect a repository when publishing an image from the command line, and to ensure your `GITHUB_TOKEN` has appropriate permissions when using a GitHub Actions workflow, we recommend adding the label `org.opencontainers.image.source` to your `Dockerfile`. For more information, see “[Labelling container images](#labelling-container-images)” in this article and “[AUTOTITLE](/packages/managing-github-packages-using-github-actions-workflows/publishing-and-installing-a-package-with-github-actions).” |
| 94 | + |
| 95 | +## Pulling container images |
1 | 96 | ## CI/CD tagging strategy for multi-environment deployments |
2 | 97 |
|
3 | 98 | A consistent tagging strategy helps trace container images back to their source commits, simplify environment promotion, and improve rollback reliability. |
@@ -74,3 +169,159 @@ docker buildx imagetools inspect ghcr.io/NAMESPACE/IMAGE_NAME:sha-a1b2c3d |
74 | 169 | Replace `NAMESPACE` with the name of the personal account or organization to which the image is scoped. |
75 | 170 |
|
76 | 171 | Both commands should report the same `Digest` value. If the digest values differ, the tags reference different image versions. |
| 172 | + |
| 173 | +### Pull by digest |
| 174 | + |
| 175 | +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. |
| 176 | + |
| 177 | +1. To find the digest SHA value, use `docker inspect` or `docker pull` and copy the SHA value after `Digest:` |
| 178 | + |
| 179 | + ```shell |
| 180 | + docker inspect {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME |
| 181 | + ``` |
| 182 | + |
| 183 | + Replace `NAMESPACE` with the name of the personal account or organization to which the image is scoped. |
| 184 | +1. Remove image locally as needed. |
| 185 | + |
| 186 | + ```shell |
| 187 | + docker rmi {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME:latest |
| 188 | + ``` |
| 189 | + |
| 190 | +1. Pull the container image with `@YOUR_SHA_VALUE` after the image name. |
| 191 | + |
| 192 | + ```shell |
| 193 | + docker pull {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME@sha256:82jf9a84u29hiasldj289498uhois8498hjs29hkuhs |
| 194 | + ``` |
| 195 | + |
| 196 | +### Pull by name |
| 197 | + |
| 198 | +```shell |
| 199 | +docker pull {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME |
| 200 | +``` |
| 201 | + |
| 202 | +Replace `NAMESPACE` with the name of the personal account or organization to which the image is scoped. |
| 203 | + |
| 204 | +### Pull by name and version |
| 205 | + |
| 206 | +Docker CLI example showing an image pulled by its name and the `1.14.1` version tag: |
| 207 | + |
| 208 | +```shell |
| 209 | +$ docker pull {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME:1.14.1 |
| 210 | +> 5e35bd43cf78: Pull complete |
| 211 | +> 0c48c2209aab: Pull complete |
| 212 | +> fd45dd1aad5a: Pull complete |
| 213 | +> db6eb50c2d36: Pull complete |
| 214 | +> Digest: sha256:ae3b135f133155b3824d8b1f62959ff8a72e9cf9e884d88db7895d8544010d8e |
| 215 | +> Status: Downloaded newer image for {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME/release:1.14.1 |
| 216 | +> {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME/release:1.14.1 |
| 217 | +``` |
| 218 | + |
| 219 | +Replace `NAMESPACE` with the name of the personal account or organization to which the image is scoped. |
| 220 | + |
| 221 | +### Pull by name and latest version |
| 222 | + |
| 223 | +```shell |
| 224 | +$ docker pull {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME:latest |
| 225 | +> latest: Pulling from NAMESPACE/IMAGE_NAME |
| 226 | +> Digest: sha256:b3d3e366b55f9a54599220198b3db5da8f53592acbbb7dc7e4e9878762fc5344 |
| 227 | +> Status: Downloaded newer image for {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME:latest |
| 228 | +> {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME:latest |
| 229 | +``` |
| 230 | + |
| 231 | +Replace `NAMESPACE` with the name of the personal account or organization to which the image is scoped. |
| 232 | + |
| 233 | +## Building container images |
| 234 | + |
| 235 | +This example builds the `hello_docker` image: |
| 236 | + |
| 237 | +```shell |
| 238 | +docker build -t hello_docker . |
| 239 | +``` |
| 240 | + |
| 241 | +## Tagging container images |
| 242 | + |
| 243 | +1. Find the ID for the Docker image you want to tag. |
| 244 | + |
| 245 | + ```shell |
| 246 | + $ docker images |
| 247 | + > REPOSITORY TAG IMAGE ID CREATED SIZE |
| 248 | + > {% data reusables.package_registry.container-registry-hostname %}/my-org/hello_docker latest 38f737a91f39 47 hours ago 91.7MB |
| 249 | + > hello-world latest fce289e99eb9 16 months ago 1.84kB |
| 250 | + ``` |
| 251 | + |
| 252 | +1. Tag your Docker image using the image ID and your desired image name and hosting destination. |
| 253 | + |
| 254 | + ```shell |
| 255 | + docker tag 38f737a91f39 {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/NEW_IMAGE_NAME:latest |
| 256 | + ``` |
| 257 | + |
| 258 | +Replace `NAMESPACE` with the name of the personal account or organization to which you want the image to be scoped. |
| 259 | + |
| 260 | +## Labelling container images |
| 261 | + |
| 262 | +{% data reusables.package_registry.about-annotation-keys %} Values for supported keys will appear on the package page for the image. |
| 263 | + |
| 264 | +For most images, you can use Docker labels to add the annotation keys to an image. For more information, see [LABEL](https://docs.docker.com/engine/reference/builder/#label) in the official Docker documentation and [Pre-Defined Annotation Keys](https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys) in the `opencontainers/image-spec` repository. |
| 265 | + |
| 266 | +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](#adding-a-description-to-multi-arch-images). |
| 267 | + |
| 268 | +The following annotation keys are supported in the {% data variables.product.prodname_container_registry %}. |
| 269 | + |
| 270 | +Key | Description |
| 271 | +------|------------ |
| 272 | +| `org.opencontainers.image.source` | The URL of the repository associated with the package. For more information, see [AUTOTITLE](/packages/learn-github-packages/connecting-a-repository-to-a-package#connecting-a-repository-to-a-container-image-using-the-command-line). |
| 273 | +| `org.opencontainers.image.description` | A text-only description limited to 512 characters. This description will appear on the package page, below the name of the package. |
| 274 | +| `org.opencontainers.image.licenses` | An 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](https://spdx.org/licenses/). |
| 275 | + |
| 276 | +To add a key as a Docker label, we recommend using the `LABEL` instruction in your `Dockerfile`. For example, if you're the user `octocat` 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`: |
| 277 | + |
| 278 | +```dockerfile |
| 279 | +LABEL org.opencontainers.image.source=https://{% ifversion fpt or ghec %}github.com{% else %}HOSTNAME{% endif %}/octocat/my-repo |
| 280 | +LABEL org.opencontainers.image.description="My container image" |
| 281 | +LABEL org.opencontainers.image.licenses=MIT |
| 282 | +``` |
| 283 | + |
| 284 | +{% data reusables.package_registry.auto-inherit-permissions-note %} |
| 285 | + |
| 286 | +Alternatively, you can add labels to an image at buildtime with the `docker build` command. |
| 287 | + |
| 288 | +```shell |
| 289 | +$ docker build \ |
| 290 | + --label "org.opencontainers.image.source=https://{% ifversion fpt or ghec %}github.com{% else %}HOSTNAME{% endif %}/octocat/my-repo" \ |
| 291 | + --label "org.opencontainers.image.description=My container image" \ |
| 292 | + --label "org.opencontainers.image.licenses=MIT" |
| 293 | +``` |
| 294 | + |
| 295 | +### Adding a description to multi-arch images |
| 296 | + |
| 297 | +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. |
| 298 | + |
| 299 | +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](https://github.com/opencontainers/image-spec/blob/main/annotations.md) in the `opencontainers/image-spec` repository. |
| 300 | + |
| 301 | +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. |
| 302 | + |
| 303 | +```json |
| 304 | +"annotations": { |
| 305 | + "org.opencontainers.image.description": "My multi-arch image" |
| 306 | +} |
| 307 | +``` |
| 308 | + |
| 309 | +For example, the following {% data variables.product.prodname_actions %} workflow step builds and pushes a multi-arch image. The `outputs` parameter sets the description for the image. |
| 310 | + |
| 311 | +```yaml |
| 312 | +{% data reusables.actions.actions-not-certified-by-github-comment %} |
| 313 | + |
| 314 | +- name: Build and push Docker image |
| 315 | + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 |
| 316 | + with: |
| 317 | + context: . |
| 318 | + file: ./Dockerfile |
| 319 | + platforms: {% raw %}${{ matrix.platforms }}{% endraw %} |
| 320 | + push: true |
| 321 | + outputs: type=image,name=target,annotation-index.org.opencontainers.image.description=My multi-arch image |
| 322 | +``` |
| 323 | +
|
| 324 | +## Troubleshooting |
| 325 | +
|
| 326 | +* The {% data variables.product.prodname_container_registry %} has a 10 GB size limit for each layer. |
| 327 | +* The {% data variables.product.prodname_container_registry %} has a 10 minute timeout limit for uploads. |
0 commit comments