Skip to content

Commit 5092d0f

Browse files
authored
Adding Annotations info + chainctl 'save-as' info (#2688)
## Type of change Documentation enhancement This PR adds documentation for two new Custom Assembly features: 1. The `--save-as` option for creating derivative container images 2. Support for adding custom annotations to Chainguard Containers It also adds a comprehensive "Annotations" section to the Chainguard Images overview page explaining OCI annotations and how to inspect them. ## What should this PR do? resolves chainguard-dev/internal-dev#20569 ## Why are we making this change? Customers need clear guidance on: - How to create multiple customized variants of the same base image without impacting existing consumers - How to add custom metadata/annotations to their containers for organizational tracking and filtering - Understanding what annotations are set on Chainguard Containers and how to inspect them These features provide more flexibility for organizations customizing Chainguard containers while maintaining separation of concerns. ## What are the acceptance criteria? - [ ] Documentation accurately describes the `--save-as` functionality and its use cases - [ ] Custom annotations documentation includes clear examples and explains restrictions - [ ] New Annotations section in overview page covers both standard OCI and Chainguard-specific annotations - [ ] Code examples are properly formatted and use consistent variable naming - [ ] All internal links are valid and correctly formatted - [ ] Content follows existing documentation style and tone ## How should this PR be tested? 1. Review the documentation for technical accuracy against the actual `chainctl` behavior 2. Verify that all command examples use consistent variable naming (`$ORGANIZATION`, `$CONTAINER`, etc.) 3. Check that internal links resolve correctly (especially links to Custom Assembly pages) 4. Confirm that the annotations examples match actual output from `docker inspect` and `crane config` 5. Ensure the new sections integrate smoothly with existing content flow Preview links: * [Annotations addition (Overview)](https://deploy-preview-2688--ornate-narwhal-088216.netlify.app/chainguard/chainguard-images/overview/#annotations) * CA via `chainctl` updates: * [save-as option](chainguard-dev/internal-dev#20569) * [custom annotations with CA](https://deploy-preview-2688--ornate-narwhal-088216.netlify.app/chainguard/chainguard-images/features/ca-docs/custom-assembly-chainctl/#adding-custom-annotations) --------- Signed-off-by: Mark Drake <mark@chainguard.dev>
1 parent 8b4aec1 commit 5092d0f

File tree

3 files changed

+168
-40
lines changed

3 files changed

+168
-40
lines changed

content/chainguard/chainguard-images/features/ca-docs/custom-assembly-chainctl.md

Lines changed: 101 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,22 @@ weight: 010
1515
toc: true
1616
---
1717

18-
Chainguard's [Custom Assembly](/chainguard/chainguard-images/features/ca-docs/custom-assembly/) is a tool that allows customers to create customized containers with extra packages added. This enables customers to reduce their risk exposure by creating container images that are tailored to their internal organization and application requirements while still having few-to-zero CVEs.
18+
Chainguard's [Custom Assembly](/chainguard/chainguard-images/features/ca-docs/custom-assembly/) is a tool that allows customers to create customized containers with extra packages and annotations added. This enables customers to reduce their risk exposure by creating container images that are tailored to their internal organization and application requirements while still having few-to-zero CVEs.
1919

2020
You can use [`chainctl`, Chainguard's command-line interface tool](/chainguard/chainctl/), to further customize your Custom Assembly builds and retrieve information about them. This guide provides an overview of the relevant `chainctl` commands and outlines how you can edit the configuration of Custom Assembly containers, as well as retrieve a list of a customized image's builds and its build logs.
2121

2222
> **Note**: This tutorial highlights using `chainctl` to interact with Custom Assembly resources. However, you can also interact with Custom Assembly using [the Chainguard console](/chainguard/chainguard-images/features/ca-docs/custom-assembly-console/), as well as [the Chainguard API](/chainguard/chainguard-images/features/ca-docs/custom-assembly-api-demo/).
2323
2424

25-
## Editing a Customized Container Image
25+
## Adding Packages to a Customized Container Image
2626

2727
To edit one of your organization's Custom Assembly container images, you can run the `chainctl image repo build edit` command:
2828

2929
```shell
30-
chainctl image repo build edit --parent $ORGANIZATION --repo $CUSTOMIZED_CONTAINER
30+
chainctl image repo build edit --parent $ORGANIZATION --repo $CONTAINER
3131
```
3232

33-
This example includes the `--parent` flag, which points to the name of your organization, and the `--repo` argument, which points to the name of your customized image. If you omit these arguments, `chainctl` will prompt you to select your organization and customized image interactively.
33+
This example includes the `--parent` flag, which points to the name of your organization, and the `--repo` argument, which points to the name of the image you want to customize. If you omit these arguments, `chainctl` will prompt you to select your organization and container image interactively.
3434

3535
This command will open up a file with your machine's default text editor. This file will contain a structure like the following:
3636

@@ -54,7 +54,7 @@ Before applying the change, `chainctl` will outline the changes you made and pro
5454
- - wget
5555
+ - bash
5656
57-
Applying build config to custom-node
57+
Applying build config to $CONTAINER
5858
Are you sure?
5959
Do you want to continue? [y,N]:
6060
```
@@ -78,33 +78,95 @@ EOF
7878
Then include this file in the `apply` command by adding the `-f` argument:
7979

8080
```shell
81-
chainctl image repo build apply -f build.yaml --parent chainguard.edu --repo custom-assembly --yes
81+
chainctl image repo build apply -f build.yaml --parent $ORGANIZATION --repo $CONTAINER --yes
8282
```
8383

8484
This command will again ask you to confirm that you want to apply the new configuration. To make this example completely declarative, this example includes `--yes` to automatically confirm the changes:
8585

8686
```
8787
Applying build config to custom-assembly
88-
  (*v1.CustomOverlay)(Inverse(protocmp.Transform, protocmp.Message{
89-
   "@type": s"chainguard.platform.registry.CustomOverlay",
90-
   "contents": protocmp.Message{
91-
   "@type": s"chainguard.platform.registry.ImageContents",
92-
   "packages": []string{
93-
-  "wolfi-base",
94-
+  "bash",
95-
-  "go",
96-
+  "curl",
97-
+  "mysql",
98-
   },
99-
   },
100-
  }))
88+
(*v1.CustomOverlay)(Inverse(protocmp.Transform, protocmp.Message{
89+
"@type": s"chainguard.platform.registry.CustomOverlay",
90+
"contents": protocmp.Message{
91+
"@type": s"chainguard.platform.registry.ImageContents",
92+
"packages": []string{
93+
- "wolfi-base",
94+
+ "bash",
95+
- "go",
96+
+ "curl",
97+
+ "mysql",
98+
},
99+
},
100+
}))
101101
102102
Are you sure?
103103
Do you want to continue? [y,N]:
104104
```
105105

106106
This approach is useful in cases where you would prefer to avoid any kind of interactivity, as in a CI/CD or other automation system.
107107

108+
### Using the `--save-as` option
109+
110+
> **Note**: The Custom Assembly `--save-as` option is currently in beta. [Contact us](https://www.chainguard.dev/contact?utm_source=cg-academy&utm_medium=referral&utm_campaign=dev-enablement) if you'd like to access this feature during the beta period.
111+
112+
When customizing a Chainguard Container with Custom Assembly, you have the option to either customize the image itself or create a new image based on the original with your customizations applied to it.
113+
114+
For example, say your organization has access to Chainguard's [`node` container image](https://images.chainguard.dev/directory/image/node/versions). If you use Custom Assembly to customize the `node` image without creating a new image, then the customizations applied to it will also apply to any users in your organization that are already consuming the image. Anyone who runs `docker pull cgr.dev/example.come/node` will download the customized image instead of the original, uncustomized one.
115+
116+
By creating a new image with Custom Assembly, you can customize the image without impacting any of the users or workflows already consuming it. You could also create multiple customized images based on the `node` container image to support specific functions.
117+
118+
To use `chainctl` to create new customized container images with Custom Assembly, you must include the `--save-as` option, like this:
119+
120+
```shell
121+
chainctl image repo build edit --parent $ORGANIZATION --repo $CONTAINER --save-as $NEW_NAME
122+
```
123+
124+
The following example command creates a new image named `custom-node` after applying the customizations:
125+
126+
```shell
127+
chainctl image repo build edit --parent example.com --repo node --save-as custom-node
128+
```
129+
130+
Once you run this example, the new container image would be accessible from the following URL:
131+
132+
```url
133+
cgr.dev/example.com/custom-node
134+
```
135+
136+
Note that you **must** pass the new image's name when using the `--save-as` option; `chainctl` will return an error if you don't include a new name. Additionally, you can only use this option with the `edit` subcommand; you cannot create a new image declaratively using the `apply` subcommand.
137+
138+
139+
## Adding Custom Annotations
140+
141+
Chainguard Containers include metadata in the form of *annotations*. These annotations provide important information about the container image's origin, contents, and characteristics.
142+
143+
With Custom Assembly, you can add custom annotations to your Chainguard Containers using `chainctl`. The process is the same as the one outlined previously for adding packages. First run a command like the following:
144+
145+
```shell
146+
chainctl image repo build edit --parent $ORGANIZATION --repo $CONTAINER
147+
```
148+
149+
In the text editor, add an `annotations` section to the bottom of the file like the following example:
150+
151+
```
152+
contents:
153+
packages:
154+
- jq
155+
- git
156+
- curl
157+
158+
annotations:
159+
"com.example.team": "platform-team"
160+
"com.example.build-timestamp": "2025-10-15T10:30:00Z"
161+
```
162+
163+
After saving and confirming these changes, Custom Assembly will add two custom annotations to the container image.
164+
165+
You can also apply custom annotations declaratively using the `apply` subcommand, as outlined previously.
166+
167+
Note that Custom Assembly blocks `org.opencontainers` and `dev.chainguard` annotations from being changed.
168+
169+
108170
## Retrieving Information about Custom Assembly Containers
109171

110172
You can also use the `list` subcommand to retrieve every one of a customized image's builds from the past 24 hours:
@@ -134,25 +196,25 @@ chainctl image repo build logs --parent $ORGANIZATION --repo $REPO
134196
This command will prompt you to select the build report you want to view. These are organized in reverse chronological order by the time of each build:
135197

136198
```
137-
Select a build report to view logs:
138-
139-
Wed, 16 Apr 2025 16:36:52 PDT - Wed, 16 Apr 2025 16:37:08 PDT Success (18-dev, 18.20-dev, 18.20.8-dev)
140-
> Wed, 16 Apr 2025 16:36:45 PDT - Wed, 16 Apr 2025 16:37:00 PDT Success (20-dev, 20.19-dev, 20.19.0-dev)
141-
Wed, 16 Apr 2025 16:36:42 PDT - Wed, 16 Apr 2025 16:36:52 PDT Success (18, 18.20, 18.20.8)
142-
Wed, 16 Apr 2025 16:36:41 PDT - Wed, 16 Apr 2025 16:36:51 PDT Success (22-slim, 22.14-slim, 22.14.0-slim)
143-
Wed, 16 Apr 2025 16:36:32 PDT - Wed, 16 Apr 2025 16:36:57 PDT Success (22-dev, 22.14-dev, 22.14.0-dev)
144-
Wed, 16 Apr 2025 16:36:32 PDT - Wed, 16 Apr 2025 16:36:44 PDT Success (20-slim, 20.19-slim, 20.19.0-slim)
145-
Wed, 16 Apr 2025 16:36:29 PDT - Wed, 16 Apr 2025 16:36:41 PDT Success (23-slim, 23.11-slim, 23.11.0-slim)
146-
Wed, 16 Apr 2025 16:36:19 PDT - Wed, 16 Apr 2025 16:36:29 PDT Success (23, 23.11, 23.11.0, latest)
147-
Wed, 16 Apr 2025 16:36:09 PDT - Wed, 16 Apr 2025 16:36:42 PDT Success (23-dev, 23.11-dev, 23.11.0-dev, latest-dev)
148-
Wed, 16 Apr 2025 16:36:09 PDT - Wed, 16 Apr 2025 16:36:31 PDT Success (20, 20.19, 20.19.0)
149-
Wed, 16 Apr 2025 16:36:09 PDT - Wed, 16 Apr 2025 16:36:31 PDT Success (22, 22.14, 22.14.0)
150-
Wed, 16 Apr 2025 16:36:09 PDT - Wed, 16 Apr 2025 16:36:18 PDT Success (18-slim, 18.20-slim, 18.20.8-slim)
151-
Wed, 16 Apr 2025 16:35:35 PDT - Wed, 16 Apr 2025 16:35:47 PDT Success
152-
153-
••••••••••••••
154-
155-
↑/k up • ↓/j down • / filter • q quit • ? more
199+
Select a build report to view logs:
200+
201+
Wed, 16 Apr 2025 16:36:52 PDT - Wed, 16 Apr 2025 16:37:08 PDT Success (18-dev, 18.20-dev, 18.20.8-dev)
202+
> Wed, 16 Apr 2025 16:36:45 PDT - Wed, 16 Apr 2025 16:37:00 PDT Success (20-dev, 20.19-dev, 20.19.0-dev)
203+
Wed, 16 Apr 2025 16:36:42 PDT - Wed, 16 Apr 2025 16:36:52 PDT Success (18, 18.20, 18.20.8)
204+
Wed, 16 Apr 2025 16:36:41 PDT - Wed, 16 Apr 2025 16:36:51 PDT Success (22-slim, 22.14-slim, 22.14.0-slim)
205+
Wed, 16 Apr 2025 16:36:32 PDT - Wed, 16 Apr 2025 16:36:57 PDT Success (22-dev, 22.14-dev, 22.14.0-dev)
206+
Wed, 16 Apr 2025 16:36:32 PDT - Wed, 16 Apr 2025 16:36:44 PDT Success (20-slim, 20.19-slim, 20.19.0-slim)
207+
Wed, 16 Apr 2025 16:36:29 PDT - Wed, 16 Apr 2025 16:36:41 PDT Success (23-slim, 23.11-slim, 23.11.0-slim)
208+
Wed, 16 Apr 2025 16:36:19 PDT - Wed, 16 Apr 2025 16:36:29 PDT Success (23, 23.11, 23.11.0, latest)
209+
Wed, 16 Apr 2025 16:36:09 PDT - Wed, 16 Apr 2025 16:36:42 PDT Success (23-dev, 23.11-dev, 23.11.0-dev, latest-dev)
210+
Wed, 16 Apr 2025 16:36:09 PDT - Wed, 16 Apr 2025 16:36:31 PDT Success (20, 20.19, 20.19.0)
211+
Wed, 16 Apr 2025 16:36:09 PDT - Wed, 16 Apr 2025 16:36:31 PDT Success (22, 22.14, 22.14.0)
212+
Wed, 16 Apr 2025 16:36:09 PDT - Wed, 16 Apr 2025 16:36:18 PDT Success (18-slim, 18.20-slim, 18.20.8-slim)
213+
Wed, 16 Apr 2025 16:35:35 PDT - Wed, 16 Apr 2025 16:35:47 PDT Success
214+
215+
••••••••••••••
216+
217+
↑/k up • ↓/j down • / filter • q quit • ? more
156218
157219
```
158220

@@ -166,4 +228,4 @@ Highlight your chosen build report and select it by pressing `ENTER`. This will
166228

167229
The `chainctl` commands outlined in this guide show how you can interact with Chainguard's Custom Assembly tool from the command line.
168230

169-
You can also interact with Custom Assembly with the [Chainguard API](/chainguard/administration/api/). Our tutorial on [Using the Chainguard API to Manage Custom Assembly Resources](/chainguard/chainguard-images/features/ca-docs/custom-assembly-api-demo/) outlines how to run a demo application that updates the configuration of a Custom Assembly container through the Chainguard API.
231+
You can also interact with Custom Assembly with the [Chainguard API](/chainguard/administration/api/). Our tutorial on [Using the Chainguard API to Manage Custom Assembly Resources](/chainguard/chainguard-images/features/ca-docs/custom-assembly-api-demo/) outlines how to run a demo application that updates the configuration of a Custom Assembly container through the Chainguard API.

content/chainguard/chainguard-images/features/ca-docs/faq.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ images: []
1212
menu:
1313
docs:
1414
parent: "features"
15-
identifier: "Custom Assembly Introduction"
15+
identifier: "Custom Assembly FAQs"
1616
weight: 002
1717
toc: true
1818
---

content/chainguard/chainguard-images/overview.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,69 @@ Once you run this command, you'll receive output similar to the following.
109109
This verifies that the Ruby Chainguard Container is built for both AMD64 and ARM64 architectures.
110110

111111
You can read more about our support of ARM64 in our blog on [Building Wolfi from the ground up](https://www.chainguard.dev/unchained/building-wolfi-from-the-ground-up-and-announcing-arm64-support?utm=docs).
112+
113+
114+
## Annotations
115+
116+
All Chainguard Containers include metadata in the form of *annotations* (also commonly referred to as "*labels*"). These annotations provide important information about a container image's origin, contents, and characteristics. The annotations are visible in every container image's **Specifications** tab in both the [Chainguard Console](https://console.chainguard.dev) and [Directory](https://images.chainguard.dev/), and can also be inspected programmatically using container tools.
117+
118+
Chainguard Containers follow the [Open Container Initiative (OCI) Image Specification](https://github.com/opencontainers/image-spec/blob/main/annotations.md) for annotations. Chainguard sets the following standard OCI annotations on its container images:
119+
120+
* `org.opencontainers.image.authors`: Contact details for the Chainguard Container's author (typically `Chainguard Team https://www.chainguard.dev/`)
121+
* `org.opencontainers.image.url`: URL to the container image's Overview page in the Chainguard Directory (for example, `https://images.chainguard.dev/directory/image/nginx/overview`)
122+
* `org.opencontainers.image.source`: URL to the source code used to build the image in the Chainguard images repository
123+
* `org.opencontainers.image.base.digest`: The SHA256 digest of the base image used to build this container image
124+
* `org.opencontainers.image.vendor`: The distributing organization, always set to `Chainguard`
125+
* `org.opencontainers.image.created`: Timestamp indicating when the image was built; specifically, this annotation is calculated from the build time of the most recently built package within the container image
126+
127+
In addition to the standard OCI annotations, Chainguard sets custom annotations (which begin with `dev.chainguard` instead of `org.opencontainers`) that provide additional context about the container image:
128+
129+
* `dev.chainguard.package.main`: The name of the primary package in the image. This may change between different versions of an image. In some situations, it may also be empty.
130+
131+
### Retrieving annotation information
132+
133+
You can inspect image annotations using [`crane`](https://github.com/google/go-containerregistry/tree/main/cmd/crane). This section's examples use [`jq`](https://jqlang.org/), a command-line JSON processor, to filter the output to only show the relevant information:
134+
135+
```shell
136+
crane manifest cgr.dev/chainguard/apko:latest | jq -r .annotations
137+
```
138+
139+
This will output all the annotations set on the image:
140+
141+
```output
142+
{
143+
"dev.chainguard.package.main": "apko",
144+
"org.opencontainers.image.authors": "Chainguard Team https://www.chainguard.dev/",
145+
"org.opencontainers.image.created": "2025-10-14T09:49:49Z",
146+
"org.opencontainers.image.source": "https://github.com/chainguard-images/images/tree/main/images/apko",
147+
"org.opencontainers.image.url": "https://images.chainguard.dev/directory/image/apko/overview",
148+
"org.opencontainers.image.vendor": "Chainguard"
149+
}
150+
```
151+
152+
Chainguard also sets these annotation values as *labels*. In the context of OCI specifications, labels are similar to annotations but the two are ultimately distinct. [This blog post](https://adrianmouat.com/posts/annotations-and-labels-in-container-images/) outlines the differences between the two.
153+
154+
You can also inspect a Chainguard Container's labels using the `crane config` command:
155+
156+
```shell
157+
crane config cgr.dev/chainguard/apko:latest | jq '.config.Labels'
158+
```
159+
160+
This returns the same output as the previous `crane` command.
161+
162+
Lastly, you can use the `docker inspect` command to inspect a container image's labels:
163+
164+
```shell
165+
docker pull cgr.dev/chainguard/apko:latest
166+
docker inspect cgr.dev/chainguard/apko:latest | jq '.[].Config.Labels'
167+
```
168+
169+
Again, this returns the same information as before. However, using `docker inspect` requires you to download the container image beforehand.
170+
171+
### Adding container image annotations
172+
173+
OCI labels are specific to a container image, not to an entire layer. This means that for base images, annotation information is often overridden later on with more accurate details after the image has been ingested. For example, the `image.author` annotation might be reset to reflect the customer consuming the container image.
174+
175+
Some users relabel their container images after they've been ingested. As an example, you may wish to add an annotation like `com.mycompany.image.source=chainguard` to your Chainguard Containers; this would allow you to filter for all the container images provided by Chainguard at `mycompany`.
176+
177+
Some package mirroring tools support this functionality, but we recommend using Chainguard's [Custom Assembly](/chainguard/chainguard-images/features/ca-docs/custom-assembly/) tool to add custom annotations to your Chainguard Containers. Refer to our guide on [managing Custom Assembly resources with `chainctl`](/chainguard/chainguard-images/features/ca-docs/custom-assembly-chainctl/#adding-custom-annotations-with-custom-assembly) for more information.

0 commit comments

Comments
 (0)