# Adding a package to a Chainguard Container

URL: https://edu.chainguard.dev/chainguard/containers/building-and-modifying/adding-packages.md
Last Modified: September 10, 2026
Tags: Chainguard Containers, Custom Assembly, Procedural

Choose how to add a package to a Chainguard Container, find the package name, apply the change, and confirm the package reached the finished image.

Chainguard Containers ship with only the packages their application needs, so sooner or later you&rsquo;ll want one that isn&rsquo;t there. Custom Assembly is the supported way to add it. You declare the package you want, Chainguard builds the image on its own infrastructure, and Chainguard rebuilds that image whenever the package is updated. You can drive Custom Assembly from the Chainguard Console, interactively with chainctl, or non-interactively with chainctl from a pipeline.
This page helps you pick an approach, then covers the three steps that apply whichever one you pick: finding the package name, adding the package, and confirming that it reached the finished image.
Choose an approach The following table compares the available approaches:
Approach Use it when What you need Custom Assembly in the Console You want to browse the packages your organization can add and apply the change in a few clicks. A Console account with a role that has the repo.update capability. Custom Assembly with chainctl, interactively You work from a terminal and want to review a diff before it applies. chainctl, installed and authenticated. Custom Assembly with chainctl, non-interactively You keep image configuration in version control or apply it from CI/CD. chainctl and a YAML build configuration file. Custom Assembly with the Chainguard API You&rsquo;re building your own tooling around Custom Assembly. An API client and a Chainguard token. apk add in a Dockerfile You build on a -dev variant or on wolfi-base, and you&rsquo;re prepared to pin package versions and image digests yourself. A Dockerfile and a container image that includes apk. apk with chroot in a multi-stage build You need a package in a distroless image and Custom Assembly doesn&rsquo;t fit your workflow. A multi-stage Dockerfile. Custom Assembly is the recommended approach because Chainguard&rsquo;s build pipeline resolves the packages you add against the packages already in the base image, then rebuilds the image when any of them change. Adding packages with apk add in your own Dockerfile moves that work to you: without pinned package versions and image digests, a package update can conflict with an older dependency in the base image and break your build until a new base image is released. For the longer version of this argument, see Why use Custom Assembly for adding packages.
Note: Custom Assembly is available to organizations with access to production Chainguard Containers. If you use Chainguard&rsquo;s free container images, take one of the Dockerfile approaches.
Before you begin The Custom Assembly approaches on this page share these prerequisites:
Access to production Chainguard Containers. A role with the repo.update capability, to customize an existing image in place, or the repo.create capability, to save the result as a new image. Of Chainguard&rsquo;s three default roles — viewer, editor, and owner — only owner has both. For a custom role you can create instead, see Custom Assembly permissions requirements. For the chainctl approaches, chainctl installed and authenticated. Custom Assembly adds packages to an image; it can&rsquo;t remove the packages the source image already contains. You can, however, remove packages you added in an earlier build.
Find the package name You can add only the packages your organization is entitled to, which are the packages that appear in the Chainguard Containers you already have access to. Package names often carry a version stream — python-3.14 rather than python — so confirm the exact name before you add it. Look it up in the Console, or with apk from inside a running container.
Open the image in the Chainguard Console, click Customize image, then use the Filter packages box. The list holds every package your organization can add. If the package you want isn&rsquo;t listed, open a Chainguard support ticket.
Container images that include apk — such as a -dev variant — can search the repository from inside a running container. For a free container image, no authentication is needed:
docker run --rm --entrypoint sh cgr.dev/chainguard/wolfi-base:latest \ -c &#39;apk update &gt; /dev/null &amp;&amp; apk search -e &#34;mongo*&#34;&#39;mongo-tools-100.18.0-r6 mongodb-kubernetes-operator-0.13.0-r14 mongodb-kubernetes-operator-compat-0.13.0-r14 mongodb-kubernetes-operator-readinessprobe-0.13.0-r14To search the packages your organization is entitled to, start a -dev variant of one of your organization&rsquo;s images with an HTTP_AUTH variable so that apk can reach your Private APK Repository:
docker run -it --rm --entrypoint /bin/sh --user root \ -e &#34;HTTP_AUTH=basic:apk.cgr.dev:user:$(chainctl auth token --audience apk.cgr.dev)&#34; \ cgr.dev/$ORGANIZATION/$CONTAINER:latest-devFrom the container&rsquo;s shell, run apk update and then apk search.
Add the package The three procedures below all produce the same result. Pick the tab that matches how you work.
In the Chainguard Console, open the image you want to customize. Click Customize image, then select the packages to add. Click Continue, then choose Create a new image or Customize current image. Click Preview changes and review the package list. Click Apply changes. For the full walkthrough, including how to edit or remove customizations later, see Using the Chainguard Console to manage Custom Assembly resources.
Open the image&rsquo;s build configuration:
chainctl images repos build edit --parent $ORGANIZATION --repo $CONTAINERReplace $ORGANIZATION with your organization&rsquo;s name and $CONTAINER with the name of the image. If you omit either flag, chainctl prompts you to choose.
chainctl opens the configuration in your default text editor. Add the package under contents.packages:
contents: packages: - yarn - wget - bash Save and close the file. chainctl prints a diff and asks you to confirm:
/tmp/3352123767.yaml (-deletion / &#43;addition): contents: packages: - yarn - wget &#43; - bash Applying build config to $CONTAINER Are you sure? Do you want to continue? [y,N]: Enter y to start the build.
To save the result as a new image rather than changing the existing one, add --save-as $NEW_NAME. For the rest of what you can set in this file, including environment variables, annotations, and custom user accounts, see Using chainctl to manage Custom Assembly resources.
Both apply and edit accept a configuration file, which skips the editor and the prompt. Use this form in CI/CD and anywhere you keep image configuration in version control.
Write the build configuration to a file:
cat &gt; build.yaml &lt;&lt;EOF contents: packages: - bash - curl - mysql EOF Preview what the file would change, without changing anything:
chainctl images repos build apply -f build.yaml --parent $ORGANIZATION --repo $CONTAINER --dry-run--dry-run prints the diff and exits with a non-zero status if there&rsquo;s anything to apply, which makes it usable as a drift check in a pipeline.
Apply the configuration. --yes confirms the change without prompting:
chainctl images repos build apply -f build.yaml --parent $ORGANIZATION --repo $CONTAINER --yes To save the result as a new image, add --save-as $NEW_NAME. This works when you target a single repository; it isn&rsquo;t available when you target several at once with repeated --repo flags or a wildcard.
For a worked GitHub Actions pipeline built around these commands, see Using GitOps to manage Custom Assembly resources.
Confirm the package is in the image Custom Assembly builds run on Chainguard&rsquo;s infrastructure and normally finish in under 20 minutes, so your change won&rsquo;t reach the registry immediately.
Check that the build succeeded:
chainctl images repos build list --parent $ORGANIZATION --repo $CONTAINER START TIME | COMPLETION TIME | RESULT | TAGS -------------------------------|-------------------------------|---------|------------------------------- Wed, 09 Sep 2026 12:46:56 CDT | Wed, 09 Sep 2026 12:47:13 CDT | Success | 26-full, 26.8-full, latest-full Wed, 09 Sep 2026 12:45:22 CDT | Wed, 09 Sep 2026 12:46:13 CDT | Success | 26-dev, 26.8-dev, latest-devThe Console shows the same information on the image&rsquo;s Builds tab. Builds stay listed for 24 hours.
Pull the image:
docker pull cgr.dev/$ORGANIZATION/$CONTAINER:latest Check for the package. If the image includes apk, query it directly. apk info -e prints the package name when the package is installed and exits with a non-zero status when it isn&rsquo;t:
docker run --rm --entrypoint apk \ cgr.dev/$ORGANIZATION/$CONTAINER:latest-dev info -e bashbashDistroless images have no apk, so read the image&rsquo;s SBOM instead. This command lists the apk packages in the image:
cosign download attestation \ --platform linux/amd64 \ --predicate-type https://spdx.dev/Document \ cgr.dev/$ORGANIZATION/$CONTAINER:latest \ | jq -r &#39;.payload&#39; | base64 -d \ | jq -r &#39;.predicate.packages[] | select(.externalRefs[]?.referenceLocator? // &#34;&#34; | startswith(&#34;pkg:apk/&#34;)) | .name&#39;ca-certificates-bundle gdbm glibc-2.44 ld-linux-2.44 python-3.14The Console shows the same list on the image&rsquo;s SBOM tab. For more ways to read this data, see Retrieving Chainguard Container SBOMs.
If the build fails A Custom Assembly build reports failure only after it finishes. Retrieve the logs for a build with the logs subcommand, which prompts you to pick a build report:
chainctl images repos build logs --parent $ORGANIZATION --repo $CONTAINERIn the Console, click a row on the image&rsquo;s Builds tab to open the same logs.
Builds fail for a few recurring reasons:
Two packages install the same file, and Custom Assembly can&rsquo;t resolve the conflict. A package is newer than the base image and was built against a newer version of glibc. The build ran longer than an hour and timed out. The package isn&rsquo;t one your organization is entitled to. For more on these cases, see Custom Assembly troubleshooting. If you can&rsquo;t resolve a failure, contact Chainguard support.
Learn more Overview of Chainguard Custom Assembly covers what Custom Assembly can change, its limitations, and how the CVE remediation SLA applies to customized images. Custom Assembly FAQs answers questions about entitlements, FIPS, and support boundaries. Overview of Chainguard&rsquo;s package repositories explains where the packages you can add come from. Adding custom certificates with Custom Assembly covers embedding internal CA certificates in an image. 
