Skip to content

Commit 8f7f425

Browse files
Update Artifactory packages pull-through guide to use Docker build secrets (#3304)
## Summary - Replaces hardcoded Artifactory tokens in `/etc/apk/repositories` with Docker build secrets (`--mount=type=secret`), preventing tokens from being stored in image layers or appearing in `docker history` - Combines repository configuration, package installation, and cleanup into a single `RUN` instruction so credentials never persist in a layer - Updates `docker build` commands to pass tokens via `--secret id=...,env=...` and non-sensitive config via `--build-arg` - Applies the same pattern to both the private APK (`cg-private`) and public repo (`cg-chainguard`, `cg-extras`) Dockerfiles Fixes: chainguard-dev/internal#5839 ## Test plan - [ ] Verify Dockerfiles render correctly in the [site preview](https://deploy-preview-3304--ornate-narwhal-088216.netlify.app/chainguard/chainguard-images/chainguard-registry/pull-through-guides/artifactory/artifactory-packages-pull-through/#testing-pull-through-from-private-apk-repository) - [ ] Confirm the `<<'EOF'` heredoc syntax is accurate (single-quoted to prevent shell expansion) - [ ] Spot-check that `--secret id=...,env=...` and `--mount=type=secret` syntax is correct for current Docker Buildx - [ ] Review for tone and style consistency with surrounding content 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 875a1d8 commit 8f7f425

1 file changed

Lines changed: 36 additions & 16 deletions

File tree

  • content/chainguard/chainguard-images/chainguard-registry/pull-through-guides/artifactory/artifactory-packages-pull-through

content/chainguard/chainguard-images/chainguard-registry/pull-through-guides/artifactory/artifactory-packages-pull-through/index.md

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -129,31 +129,41 @@ In this example, the Artifactory username is `linky` and the hostname is `exampl
129129

130130
This section outlines how to build a container image using a Chainguard image as a base and configure it to pull packages from the private APK repositories through your remote Artifactory repository.
131131

132-
Open a terminal and create a Dockerfile:
132+
Open a terminal and create a Dockerfile. Note the use of single quotes around `'EOF'` to prevent the shell from expanding the `$` variables — these will be processed by Docker during the build:
133133

134134
```shell
135-
cat > Dockerfile <<EOF
135+
cat > Dockerfile <<'EOF'
136136
FROM cgr.dev/chainguard/python:latest-dev
137137
USER root
138-
RUN cp /etc/apk/repositories /etc/apk/repositories.disabled
139-
RUN echo 'https://$ARTIFACTORY_USERNAME:$CG_PRIVATE_TOKEN@$ARTIFACTORY_SERVER_NAME.jfrog.io/artifactory/cg-private/' > /etc/apk/repositories
140-
RUN apk add sed
138+
ARG ARTIFACTORY_USERNAME
139+
ARG ARTIFACTORY_SERVER_NAME
140+
RUN --mount=type=secret,id=cg_private_token \
141+
cp /etc/apk/repositories /etc/apk/repositories.disabled && \
142+
echo "https://${ARTIFACTORY_USERNAME}:$(cat /run/secrets/cg_private_token)@${ARTIFACTORY_SERVER_NAME}.jfrog.io/artifactory/cg-private/" > /etc/apk/repositories && \
143+
apk add sed && \
144+
rm /etc/apk/repositories
141145
USER nonroot
142146
EOF
143147
```
144148

145149
This Dockerfile uses the `python:latest-dev` image. You don't have to use this particular image, but because we are using the `apk` command to install a package from `cgr-private` in this Dockerfile, you should use a Chainguard container image that has this package manager available.
146150

147-
Note that this Dockerfile renames the default `/etc/apk/repositories` file. This isn't necessary, but doing so allows you to ensure that you're actually downloading packages from the remote Artifactory repositories instead of the default ones.
151+
Note that this Dockerfile combines the repository configuration, package installation, and cleanup into a single `RUN` instruction. This is important because it ensures the Artifactory token is never stored in an image layer. The `--mount=type=secret` option mounts the token only for the duration of this `RUN` instruction and it is not written to the image or its history. The final `rm` removes the `/etc/apk/repositories` file, which contained the token in plain text for the duration of the step.
148152

149153
Additionally, be aware that there are limitations to what packages are available from your organization's private APK repository. For instance, your organization may not have access to the `sed` package. Refer to our [private APK repository documentation](/chainguard/chainguard-images/features/private-apk-repos/#about-private-apk-repositories) for more information.
150154

151-
After creating the Dockerfile, build the image. Here, we tag the image `ar-build`:
155+
After creating the Dockerfile, build the image. Here, we tag the image `ar-build` and pass the Artifactory token as a Docker build secret along with the username and server name as build arguments:
152156

153157
```shell
154-
docker build -t ar-build .
158+
docker build \
159+
--secret id=cg_private_token,env=CG_PRIVATE_TOKEN \
160+
--build-arg ARTIFACTORY_USERNAME=$ARTIFACTORY_USERNAME \
161+
--build-arg ARTIFACTORY_SERVER_NAME=$ARTIFACTORY_SERVER_NAME \
162+
-t ar-build .
155163
```
156164

165+
The `--secret` flag passes `CG_PRIVATE_TOKEN` as a build secret that is accessible only during the build and is never stored in the image or its history.
166+
157167
This command's output will show that the `sed` package was installed as expected:
158168

159169
```output
@@ -214,23 +224,33 @@ Then for the `cg-extras` repo's token:
214224
export EXTRAS_TOKEN=<cg-extras-token>
215225
```
216226

217-
Following that, you can use these environment variables, along with a few created earlier in the guide, to create a Dockerfile as you previously did for the `cg-private` repository:
227+
Following that, you can create a Dockerfile for the public repositories. As before, use single quotes around `'EOF'` to prevent shell expansion:
218228

219229
```shell
220-
cat > Dockerfile.repos <<EOF
230+
cat > Dockerfile.repos <<'EOF'
221231
FROM cgr.dev/chainguard/python:latest-dev
222232
USER root
223-
RUN cp /etc/apk/repositories /etc/apk/repositories.disabled
224-
RUN echo 'https://$ARTIFACTORY_USERNAME:$CG_TOKEN@$ARTIFACTORY_SERVER_NAME.jfrog.io/artifactory/cg-chainguard/' > /etc/apk/repositories
225-
RUN echo 'https://$ARTIFACTORY_USERNAME:$EXTRAS_TOKEN@$ARTIFACTORY_SERVER_NAME.jfrog.io/artifactory/cg-extras/' >> /etc/apk/repositories
226-
RUN apk add c-ares
233+
ARG ARTIFACTORY_USERNAME
234+
ARG ARTIFACTORY_SERVER_NAME
235+
RUN --mount=type=secret,id=cg_token \
236+
--mount=type=secret,id=extras_token \
237+
cp /etc/apk/repositories /etc/apk/repositories.disabled && \
238+
echo "https://${ARTIFACTORY_USERNAME}:$(cat /run/secrets/cg_token)@${ARTIFACTORY_SERVER_NAME}.jfrog.io/artifactory/cg-chainguard/" > /etc/apk/repositories && \
239+
echo "https://${ARTIFACTORY_USERNAME}:$(cat /run/secrets/extras_token)@${ARTIFACTORY_SERVER_NAME}.jfrog.io/artifactory/cg-extras/" >> /etc/apk/repositories && \
240+
apk add c-ares && \
241+
rm /etc/apk/repositories
227242
EOF
228243
```
229244

230-
Following that, build the image:
245+
Following that, build the image, passing each Artifactory token as a Docker build secret:
231246

232247
```shell
233-
docker build -t ar-repos -f Dockerfile.repos .
248+
docker build \
249+
--secret id=cg_token,env=CG_TOKEN \
250+
--secret id=extras_token,env=EXTRAS_TOKEN \
251+
--build-arg ARTIFACTORY_USERNAME=$ARTIFACTORY_USERNAME \
252+
--build-arg ARTIFACTORY_SERVER_NAME=$ARTIFACTORY_SERVER_NAME \
253+
-t ar-repos -f Dockerfile.repos .
234254
```
235255

236256
As this command runs, it installs the `c-ares` package into the image.

0 commit comments

Comments
 (0)