Prerequisites
Before you begin, ensure you have:
- A Root account with an active subscription (app.root.io)
- A Root API token (generated from the Root dashboard)
- Docker with BuildKit support (Docker 23.0+ or
DOCKER_BUILDKIT=1)
- A Dockerfile that installs OS packages via
apt-get or apk
Step 1: Generate an API Token
- Log in to app.root.io.
- Navigate to Settings → API Tokens.
- Click Generate Token.
- Copy the token value. You will need it to authenticate with
pkg.root.io.
Store your API token in a secrets manager (e.g., AWS Secrets Manager, HashiCorp Vault, or your CI/CD platform’s secrets store). Pass it to Docker builds using BuildKit secrets — never hard-code the token in your Dockerfile or commit it to version control.
All examples use Docker BuildKit’s --mount=type=secret to pass the API key securely. The key never appears in any image layer.
Ubuntu (APT)
Debian (APT)
Alpine (APK)
# syntax=docker/dockerfile:1.6
FROM ubuntu:noble
RUN --mount=type=secret,id=rootio_api_key \
DEBIAN_FRONTEND=noninteractive apt-get update && \
# Install dependencies for adding repositories
apt-get install -y --no-install-recommends gnupg ca-certificates && \
\
# Initialize keyring and add Root.io GPG key
mkdir -p /etc/apt/keyrings && \
echo "LS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tCgptRE1FYVlIQ1dSWUpLd1lCQkFIYVJ3OEJBUWRBcDdXVHNLMTVrWTNmQ0pxOUNRVnlxODluRzFoNEw4OHZvVndqCnB0NGNXSjYwSkZKdmIzUXVhVzhnUVZCVUlGSmxjRzl6YVhSdmNua2dQR0Z3ZEVCeWIyOTBMbWx2UG9pVEJCTVcKQ2dBN0ZpRUUzSVVhWTlLRDFsTUhKYTdNZ09RM004RHd3c2tGQW1tQndsa0NHd01GQ3drSUJ3SUNJZ0lHRlFvSgpDQXNDQkJZQ0F3RUNIZ2NDRjRBQUNna1FnT1EzTThEd3dzbGY2d0QrSWxqSGRkVmFKM2xKYjBsSE0rZVFubWNvCnlmTTlpWis5cXI0SjBNYnZsNG9CQUtOL0pYZkJvR2JGYzgzM0ZmN1I5R3M5UXU2bm1EUVZlSDI4eHEwdDRwWU4KPWs3ZHMKLS0tLS1FTkQgUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLQo=" \
| base64 -d | gpg --dearmor -o /etc/apt/keyrings/rootio.gpg && \
\
# Write API key to auth.conf.d (never embedded in the source URL)
mkdir -p /etc/apt/auth.conf.d && \
printf "machine pkg.root.io\nlogin root\npassword %s\n" \
"$(cat /run/secrets/rootio_api_key)" > /etc/apt/auth.conf.d/rootio.conf && \
chmod 600 /etc/apt/auth.conf.d/rootio.conf && \
\
# Add Root.io APT repository
echo "deb [signed-by=/etc/apt/keyrings/rootio.gpg] https://pkg.root.io/ubuntu/noble noble main" \
> /etc/apt/sources.list.d/rootio.list && \
\
DEBIAN_FRONTEND=noninteractive apt-get update && \
\
# Install packages, preferring Root.io patched versions when available
for pkg in curl git openssl wget bash tini; do \
if apt-cache show "rootio-$pkg" >/dev/null 2>&1; then \
apt-get install -y --no-install-recommends "rootio-$pkg"; \
else \
apt-get install -y --no-install-recommends "$pkg"; \
fi; \
done && \
\
# Remove credentials and clean up
rm -f /etc/apt/auth.conf.d/rootio.conf && \
rm -rf /var/lib/apt/lists/*
CMD ["/bin/bash"]
Supported Ubuntu releases: focal, jammy, mantic, noble, oracularReplace noble in both the echo and sources.list.d lines with your distro codename.# syntax=docker/dockerfile:1.6
FROM debian:bookworm-slim
RUN --mount=type=secret,id=rootio_api_key \
DEBIAN_FRONTEND=noninteractive apt-get update && \
# Install dependencies for adding repositories
apt-get install -y --no-install-recommends gnupg ca-certificates && \
\
# Initialize keyring and add Root.io GPG key
mkdir -p /etc/apt/keyrings && \
echo "LS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tCgptRE1FYVlIQ1dSWUpLd1lCQkFIYVJ3OEJBUWRBcDdXVHNLMTVrWTNmQ0pxOUNRVnlxODluRzFoNEw4OHZvVndqCnB0NGNXSjYwSkZKdmIzUXVhVzhnUVZCVUlGSmxjRzl6YVhSdmNua2dQR0Z3ZEVCeWIyOTBMbWx2UG9pVEJCTVcKQ2dBN0ZpRUUzSVVhWTlLRDFsTUhKYTdNZ09RM004RHd3c2tGQW1tQndsa0NHd01GQ3drSUJ3SUNJZ0lHRlFvSgpDQXNDQkJZQ0F3RUNIZ2NDRjRBQUNna1FnT1EzTThEd3dzbGY2d0QrSWxqSGRkVmFKM2xKYjBsSE0rZVFubWNvCnlmTTlpWis5cXI0SjBNYnZsNG9CQUtOL0pYZkJvR2JGYzgzM0ZmN1I5R3M5UXU2bm1EUVZlSDI4eHEwdDRwWU4KPWs3ZHMKLS0tLS1FTkQgUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLQo=" \
| base64 -d | gpg --dearmor -o /etc/apt/keyrings/rootio.gpg && \
\
# Write API key to auth.conf.d (never embedded in the source URL)
mkdir -p /etc/apt/auth.conf.d && \
printf "machine pkg.root.io\nlogin root\npassword %s\n" \
"$(cat /run/secrets/rootio_api_key)" > /etc/apt/auth.conf.d/rootio.conf && \
chmod 600 /etc/apt/auth.conf.d/rootio.conf && \
\
# Add Root.io APT repository
echo "deb [signed-by=/etc/apt/keyrings/rootio.gpg] https://pkg.root.io/debian/bookworm bookworm main" \
> /etc/apt/sources.list.d/rootio.list && \
\
DEBIAN_FRONTEND=noninteractive apt-get update && \
\
# Install packages, preferring Root.io patched versions when available
for pkg in curl git openssl wget bash tini; do \
if apt-cache show "rootio-$pkg" >/dev/null 2>&1; then \
apt-get install -y --no-install-recommends "rootio-$pkg"; \
else \
apt-get install -y --no-install-recommends "$pkg"; \
fi; \
done && \
\
# Remove credentials and clean up
rm -f /etc/apt/auth.conf.d/rootio.conf && \
rm -rf /var/lib/apt/lists/*
CMD ["/bin/bash"]
Supported Debian releases: bullseye, bookworm, trixieReplace bookworm in both the echo and sources.list.d lines with your distro codename.# syntax=docker/dockerfile:1.6
ARG ALPINE_VERSION=3.20
FROM alpine:${ALPINE_VERSION}
ARG ALPINE_VERSION
RUN --mount=type=secret,id=rootio_api_key \
# Install Root.io Alpine signing key
echo "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFvcG1yUjR1em95WEFiTHFiRUE3cwpBNWQrVytnUzE0TzEwMlJHUjhxa0h0cDhSUEs2b3FvZkhJZzNYSWpnSVlzalQwYTk1VXNzbGFlL2FDWU1UeFBVCmhnSmxkTVU1SnlzZmYxT1BEQld4R2ZCOFJCL081cjA1cU9JLzJ3QlgwQjl5NjhhU0xQZi9UWEA3akY5STRKL3EKdjArWVF2c3owRWdqUEFjeVN2MlgvOHE2R2RoOHRkWG4rbTVBYjJoUU5YUE1TdTM3aXMwUVR3Uk9DSFV4ZXZLeAo0OUZ5UGkvQUR5UDB6bVFYaUtCQW52alN6YVNQNmZPQm1yYlNNY05wYnVPV2lwUUJoajRnVE5KOVNzaDZSQmdmCmJVUlFhdmlwWlAyL0RiNTNiLzJ5UTJJU21QMEo1cmdjWnkrdXoyZndTWmtHb3pUa0ErZDE1dHludlJRVFQwbGkKWXdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==" | \
base64 -d > /etc/apk/keys/root@alpinelinux.org-67b85bd5.rsa.pub && \
\
# Add pkg.root.io repository with credentials from secret
echo "https://root:$(cat /run/secrets/rootio_api_key)@pkg.root.io/alpine/${ALPINE_VERSION}" \
>> /etc/apk/repositories && \
\
apk update && \
\
# Install packages, preferring Root.io patched versions when available
for pkg in curl git openssl wget tini; do \
if apk search -e "rootio-$pkg" | grep -q "rootio-$pkg"; then \
apk add --no-cache "rootio-$pkg"; \
else \
apk add --no-cache "$pkg"; \
fi; \
done && \
\
# Remove repository credentials
sed -i '/pkg\.root\.io/d' /etc/apk/repositories
CMD ["/bin/sh"]
Supported Alpine versions: 3.18–3.22
Step 3: Build Your Image
Pass your API token as a BuildKit secret at build time:
DOCKER_BUILDKIT=1 docker build \
--secret id=rootio_api_key,env=ROOTIO_API_KEY \
-t my-app:latest .
Set the environment variable before building:
export ROOTIO_API_KEY="your-api-token"
The --secret flag requires BuildKit. It ensures your API key is only available inside the RUN step that mounts it and never written to any image layer.
Step 4: Verify Installation
After building, confirm that Root-patched packages were installed:
# Enter the container
docker run --rm -it my-app:latest /bin/bash
# Debian / Ubuntu — check for rootio- packages
dpkg -l | grep rootio
# Alpine — check for rootio- packages
apk list --installed | grep rootio
You should see rootio-curl, rootio-git, etc. for every package that Root has a patched version available.
Step 5: CI/CD Integration
- name: Build container image
env:
ROOTIO_API_KEY: ${{ secrets.ROOTIO_API_KEY }}
run: |
DOCKER_BUILDKIT=1 docker build \
--secret id=rootio_api_key,env=ROOTIO_API_KEY \
-t my-app:latest .
build:
variables:
DOCKER_BUILDKIT: "1"
ROOTIO_API_KEY: $ROOTIO_API_KEY
script:
- docker build
--secret id=rootio_api_key,env=ROOTIO_API_KEY
-t my-app:latest .
Troubleshooting
401 Unauthorized when running apt-get update
Your API token is missing or invalid. Verify the secret is being passed correctly with --secret id=rootio_api_key,env=ROOTIO_API_KEY and that ROOTIO_API_KEY is set in your environment.
rootio-<package> not found
Root hasn’t patched this package yet. The fallback pattern (apt-cache show / apk search) ensures your build succeeds with the upstream version. You can request the package via the Root UI.
GPG key import fails
Ensure gnupg and ca-certificates are installed before importing the key. These must be installed from the upstream repository first.
--secret flag not recognized
BuildKit is not enabled. Prepend DOCKER_BUILDKIT=1 to your build command or set it as an environment variable.
What’s Next