Skip to content

Commit d771e4c

Browse files
author
Divanshu
authored
Merge pull request #1 from dvanhu/fix-ghcr-tagging-docs-1
docs: add CI/CD tagging strategy guidance
2 parents e7e8ebb + 02be38a commit d771e4c

1 file changed

Lines changed: 59 additions & 234 deletions

File tree

Lines changed: 59 additions & 234 deletions
Original file line numberDiff line numberDiff line change
@@ -1,251 +1,76 @@
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-
---
1+
## CI/CD tagging strategy for multi-environment deployments
232

24-
{% data reusables.package_registry.container-registry-ghes-beta %}
3+
A consistent tagging strategy helps trace container images back to their source commits, simplify environment promotion, and improve rollback reliability.
254

26-
## About the {% data variables.product.prodname_container_registry %}
5+
### Recommended tag scheme
276

28-
{% data reusables.package_registry.container-registry-benefits %}
7+
Apply multiple tags to the same image digest during each build so deployments can reference images by stability level or exact provenance.
298

30-
{% ifversion ghes %}
9+
| Tag pattern | Example | Purpose |
10+
|---|---|---|
11+
| Commit SHA (short) | `sha-a1b2c3d` | Immutable reference suitable for production rollbacks |
12+
| Branch name | `main`, `release-1.4` | Mutable tag that tracks the latest build for a branch |
13+
| Semantic version | `v1.4.2` | Human-readable release version |
14+
| Environment label | `staging`, `production` | Alias used during environment promotion workflows |
3115

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).
16+
> [!NOTE]
17+
> Avoid relying solely on the `latest` tag in automated deployment pipelines. Because `latest` is mutable, it does not provide reliable traceability between deployments and source revisions.
3318
34-
{% endif %}
19+
### Applying multiple tags in a GitHub Actions workflow
3520

36-
{% ifversion ghec %}
21+
Use the `docker/metadata-action` action to generate image tags automatically from Git context and pass them to `docker/build-push-action`.
3722

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
96-
97-
### Pull by digest
98-
99-
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.
100-
101-
1. To find the digest SHA value, use `docker inspect` or `docker pull` and copy the SHA value after `Digest:`
102-
103-
```shell
104-
docker inspect {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME
105-
```
106-
107-
Replace `NAMESPACE` with the name of the personal account or organization to which the image is scoped.
108-
1. Remove image locally as needed.
109-
110-
```shell
111-
docker rmi {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME:latest
112-
```
113-
114-
1. Pull the container image with `@YOUR_SHA_VALUE` after the image name.
115-
116-
```shell
117-
docker pull {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME@sha256:82jf9a84u29hiasldj289498uhois8498hjs29hkuhs
118-
```
119-
120-
### Pull by name
121-
122-
```shell
123-
docker pull {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME
23+
```yaml
24+
jobs:
25+
build-and-push:
26+
runs-on: ubuntu-latest
27+
28+
permissions:
29+
contents: read
30+
packages: write
31+
32+
steps:
33+
- name: Check out repository
34+
uses: actions/checkout@v4
35+
36+
- name: Log in to the Container registry
37+
uses: docker/login-action@v3
38+
with:
39+
registry: ghcr.io
40+
username: ${{ github.actor }}
41+
password: ${{ secrets.GITHUB_TOKEN }}
42+
43+
- name: Extract Docker metadata
44+
id: meta
45+
uses: docker/metadata-action@v5
46+
with:
47+
images: ghcr.io/${{ github.repository }}
48+
tags: |
49+
type=sha,prefix=sha-,format=short
50+
type=ref,event=branch
51+
type=semver,pattern={{version}}
52+
type=raw,value=staging,enable=${{ github.ref == 'refs/heads/main' }}
53+
54+
- name: Build and push Docker image
55+
uses: docker/build-push-action@v5
56+
with:
57+
context: .
58+
push: true
59+
tags: ${{ steps.meta.outputs.tags }}
60+
labels: ${{ steps.meta.outputs.labels }}
12461
```
12562
126-
Replace `NAMESPACE` with the name of the personal account or organization to which the image is scoped.
63+
All tags generated during the workflow reference the same image digest. This allows deployments to promote existing images between environments without rebuilding the container image.
12764
128-
### Pull by name and version
65+
### Verifying tag-to-digest traceability
12966
130-
Docker CLI example showing an image pulled by its name and the `1.14.1` version tag:
67+
After pushing an image, you can verify that multiple tags reference the same digest.
13168
132-
```shell
133-
$ docker pull {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME:1.14.1
134-
> 5e35bd43cf78: Pull complete
135-
> 0c48c2209aab: Pull complete
136-
> fd45dd1aad5a: Pull complete
137-
> db6eb50c2d36: Pull complete
138-
> Digest: sha256:ae3b135f133155b3824d8b1f62959ff8a72e9cf9e884d88db7895d8544010d8e
139-
> Status: Downloaded newer image for {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME/release:1.14.1
140-
> {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME/release:1.14.1
69+
```bash
70+
docker buildx imagetools inspect ghcr.io/NAMESPACE/IMAGE_NAME:staging
71+
docker buildx imagetools inspect ghcr.io/NAMESPACE/IMAGE_NAME:sha-a1b2c3d
14172
```
14273

14374
Replace `NAMESPACE` with the name of the personal account or organization to which the image is scoped.
14475

145-
### Pull by name and latest version
146-
147-
```shell
148-
$ docker pull {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME:latest
149-
> latest: Pulling from NAMESPACE/IMAGE_NAME
150-
> Digest: sha256:b3d3e366b55f9a54599220198b3db5da8f53592acbbb7dc7e4e9878762fc5344
151-
> Status: Downloaded newer image for {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME:latest
152-
> {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/IMAGE_NAME:latest
153-
```
154-
155-
Replace `NAMESPACE` with the name of the personal account or organization to which the image is scoped.
156-
157-
## Building container images
158-
159-
This example builds the `hello_docker` image:
160-
161-
```shell
162-
docker build -t hello_docker .
163-
```
164-
165-
## Tagging container images
166-
167-
1. Find the ID for the Docker image you want to tag.
168-
169-
```shell
170-
$ docker images
171-
> REPOSITORY TAG IMAGE ID CREATED SIZE
172-
> {% data reusables.package_registry.container-registry-hostname %}/my-org/hello_docker latest 38f737a91f39 47 hours ago 91.7MB
173-
> hello-world latest fce289e99eb9 16 months ago 1.84kB
174-
```
175-
176-
1. Tag your Docker image using the image ID and your desired image name and hosting destination.
177-
178-
```shell
179-
docker tag 38f737a91f39 {% data reusables.package_registry.container-registry-hostname %}/NAMESPACE/NEW_IMAGE_NAME:latest
180-
```
181-
182-
Replace `NAMESPACE` with the name of the personal account or organization to which you want the image to be scoped.
183-
184-
## Labelling container images
185-
186-
{% data reusables.package_registry.about-annotation-keys %} Values for supported keys will appear on the package page for the image.
187-
188-
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.
189-
190-
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).
191-
192-
The following annotation keys are supported in the {% data variables.product.prodname_container_registry %}.
193-
194-
Key | Description
195-
------|------------
196-
| `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).
197-
| `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.
198-
| `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/).
199-
200-
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`:
201-
202-
```dockerfile
203-
LABEL org.opencontainers.image.source=https://{% ifversion fpt or ghec %}github.com{% else %}HOSTNAME{% endif %}/octocat/my-repo
204-
LABEL org.opencontainers.image.description="My container image"
205-
LABEL org.opencontainers.image.licenses=MIT
206-
```
207-
208-
{% data reusables.package_registry.auto-inherit-permissions-note %}
209-
210-
Alternatively, you can add labels to an image at buildtime with the `docker build` command.
211-
212-
```shell
213-
$ docker build \
214-
--label "org.opencontainers.image.source=https://{% ifversion fpt or ghec %}github.com{% else %}HOSTNAME{% endif %}/octocat/my-repo" \
215-
--label "org.opencontainers.image.description=My container image" \
216-
--label "org.opencontainers.image.licenses=MIT"
217-
```
218-
219-
### Adding a description to multi-arch images
220-
221-
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.
222-
223-
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.
224-
225-
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.
226-
227-
```json
228-
"annotations": {
229-
"org.opencontainers.image.description": "My multi-arch image"
230-
}
231-
```
232-
233-
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.
234-
235-
```yaml
236-
{% data reusables.actions.actions-not-certified-by-github-comment %}
237-
238-
- name: Build and push Docker image
239-
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
240-
with:
241-
context: .
242-
file: ./Dockerfile
243-
platforms: {% raw %}${{ matrix.platforms }}{% endraw %}
244-
push: true
245-
outputs: type=image,name=target,annotation-index.org.opencontainers.image.description=My multi-arch image
246-
```
247-
248-
## Troubleshooting
249-
250-
* The {% data variables.product.prodname_container_registry %} has a 10 GB size limit for each layer.
251-
* The {% data variables.product.prodname_container_registry %} has a 10 minute timeout limit for uploads.
76+
Both commands should report the same `Digest` value. If the digest values differ, the tags reference different image versions.

0 commit comments

Comments
 (0)