Skip to main content
Root Image Catalog works with Docker out of the box. Images are pulled from cr.root.io using standard Docker commands and credentials.

Prerequisites

  • Docker 20.10 or later
  • Root registry credentials (username and token - see Authentication)

Authentication

docker login cr.root.io \
  --username rootio \
  --password YOUR_ROOT_TOKEN
Or pipe the token to avoid it appearing in shell history:
echo "$ROOT_TOKEN" | docker login cr.root.io --username rootio --password-stdin
Docker stores credentials in ~/.docker/config.json. All subsequent pulls from cr.root.io use these credentials automatically. Credential helpers (optional): You can use any Docker-compatible credential helper (docker-credential-pass, macOS Keychain, etc.) for more secure credential storage. Configure them in ~/.docker/config.json as you would for any other registry.

Pulling Images

docker pull cr.root.io/python:3.12-slim
docker pull cr.root.io/node:20-slim
docker pull cr.root.io/nginx:1.25
Tags mirror Docker Hub exactly. cr.root.io/python:3.12-slim is the same image as docker.io/python:3.12-slim - same behavior, same entrypoints, with CVEs remediated. Multi-architecture pulls:
docker pull --platform linux/amd64 cr.root.io/python:3.12-slim
docker pull --platform linux/arm64 cr.root.io/python:3.12-slim

Updating Your Dockerfile

Change the FROM directive to use cr.root.io:
# Before
FROM python:3.12-slim

# After
FROM cr.root.io/python:3.12-slim
No other changes are needed. The image behaves identically. Using a build argument for flexibility:
ARG BASE_REGISTRY=cr.root.io
FROM ${BASE_REGISTRY}/python:3.12-slim

# Build with Root Image Catalog (default):
# docker build .

# Build with Docker Hub (override):
# docker build --build-arg BASE_REGISTRY=docker.io .
Multi-stage builds:
ARG BASE_REGISTRY=cr.root.io

FROM ${BASE_REGISTRY}/golang:1.22-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o /app/server ./cmd/server

FROM ${BASE_REGISTRY}/alpine:3.20
COPY --from=builder /app/server /usr/local/bin/server
CMD ["/usr/local/bin/server"]

Docker Compose

Use cr.root.io images in docker-compose.yml the same way:
services:
  app:
    image: cr.root.io/python:3.12-slim
    environment:
      - DATABASE_URL=postgresql://db:5432/myapp

  db:
    image: cr.root.io/postgres:16-alpine
    environment:
      - POSTGRES_PASSWORD=secret

  cache:
    image: cr.root.io/redis:7-alpine
Docker Compose inherits credentials from ~/.docker/config.json, so no extra configuration is needed after running docker login.

Registry Mirror Configuration

To use cr.root.io as a registry mirror (so all pulls transparently go through Root), configure Docker’s daemon.json:
{
  "registry-mirrors": ["https://cr.root.io"]
}
Restart Docker after making changes:
sudo systemctl restart docker
With mirror mode, docker pull python:3.12-slim automatically resolves to the Root-patched version without changing any Dockerfiles.

CI/CD with Docker

GitHub Actions:
name: Build and push
on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Log in to Root Image Catalog
        uses: docker/login-action@v3
        with:
          registry: cr.root.io
          username: rootio
          password: ${{ secrets.ROOT_TOKEN }}

      - name: Build image
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: your-registry/your-app:latest
GitLab CI:
build:
  stage: build
  before_script:
    - echo "$ROOT_TOKEN" | docker login cr.root.io --username rootio --password-stdin
  script:
    - docker build -t your-registry/your-app:latest .
    - docker push your-registry/your-app:latest
CircleCI:
jobs:
  build:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      - setup_remote_docker
      - run:
          name: Authenticate to Root registry
          command: echo "$ROOT_TOKEN" | docker login cr.root.io --username rootio --password-stdin
      - run:
          name: Build image
          command: docker build -t your-registry/your-app:latest .