Skip to content

Docker Registry Setup

This guide covers how to install and configure a private Docker registry for the Traceable Platform.

Overview

A private Docker registry is required for:

  • Airgap deployments without internet access
  • Faster image pulls from local storage
  • Compliance requirements for image storage
  • Custom image management

Prerequisites

  • Docker, Podman, or Kubernetes cluster
  • TLS certificates (self-signed or CA-signed)
  • Storage for registry data
  • (Optional) htpasswd for authentication

Pre-Setup

Create Registry Directories

mkdir -p docker-registry/{registry,cert,auth}

Directory structure:

docker-registry/
├── cert/      # TLS certificates
├── registry/  # Image storage
└── auth/      # Authentication files

Create TLS Certificate

Generate a self-signed certificate:

openssl req -nodes -x509 -sha256 -newkey rsa:4096 \
    -keyout $(pwd)/docker-registry/cert/tls.key \
    -out $(pwd)/docker-registry/cert/tls.crt \
    -days 356 \
    -subj "/CN=localhost" \
    -addext "subjectAltName = DNS:$(hostname), IP:$(hostname -i)"

Note: Update subjectAltName with your registry hostname and IP address.

Create Authentication File (Optional)

If you want to enable authentication:

htpasswd -Bc docker-registry/auth/htpasswd myuser

Note: Remove htpasswd-related configuration if authentication is not required.


Installation Methods

Method 1: Docker/Podman

Run the registry container:

docker run -d \
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/cert/tls.crt \
    -e REGISTRY_HTTP_TLS_KEY=/cert/tls.key \
    -e REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry \
    -e REGISTRY_AUTH=htpasswd \
    -e REGISTRY_AUTH_HTPASSWD_REALM=Registry-Realm \
    -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
    -v $(pwd)/docker-registry/cert:/cert \
    -v $(pwd)/docker-registry/registry:/var/lib/registry \
    -v $(pwd)/docker-registry/auth/htpasswd:/auth/htpasswd \
    -p 5000:5000 \
    --name docker-registry \
    registry:2.8.1

For Podman: Replace docker with podman.

Method 2: Docker Compose

Create docker-compose.yaml:

version: '3'
services:
  registry:
    image: registry:2.8.1
    restart: always
    ports:
    - "5000:5000"
    environment:
      REGISTRY_HTTP_TLS_KEY: /cert/tls.key
      REGISTRY_HTTP_TLS_CERTIFICATE: /cert/tls.crt
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/lib/registry
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry-Realm
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
    volumes:
      - ./docker-registry/registry:/var/lib/registry
      - ./docker-registry/cert:/cert
      - ./docker-registry/auth/htpasswd:/auth/htpasswd

Start the registry:

docker compose up -d

Method 3: Docker Swarm

Enable swarm mode:

docker swarm init

Create the service:

docker service create \
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/cert/tls.crt \
    -e REGISTRY_HTTP_TLS_KEY=/cert/tls.key \
    -e REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/data \
    -e REGISTRY_AUTH=htpasswd \
    -e REGISTRY_AUTH_HTPASSWD_REALM=Registry-Realm \
    -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
    --mount type=bind,source=$(pwd)/docker-registry/cert/,destination=/cert/ \
    --mount type=bind,source=$(pwd)/docker-registry/registry/,destination=/data/ \
    --mount type=bind,source=$(pwd)/docker-registry/auth/,destination=/auth/ \
    -p 5000:5000 \
    --name docker-registry \
    --replicas 3 \
    registry:2.8.1

Method 4: Kubernetes

Step 1: Create Secrets

# TLS certificate secret
kubectl create secret generic registry-cert \
    --from-file $(pwd)/docker-registry/cert/tls.key \
    --from-file $(pwd)/docker-registry/cert/tls.crt

# htpasswd secret
kubectl create secret generic registry-htpasswd \
    --from-file $(pwd)/docker-registry/auth/htpasswd

Step 2: Create values.yaml

replicaCount: 2
tlsSecretName: registry-cert
service:
  nodePort: 30000
  type: NodePort
persistence:
  enabled: true
  storageClass: nfs-client
secrets:
  htpasswd: registry-htpasswd

Note: Update storageClass for your environment. If the storage class doesn't support multi-node mounting, all pods will be scheduled on one node.

Step 3: Add Helm Repository

helm repo add twuni https://helm.twun.io

Step 4: Install Registry

helm upgrade --install twuni twuni/docker-registry --values ./values.yaml

Client Configuration

Add Certificate to Trust Store

For self-signed certificates, add the certificate to the client's trust store.

Find trust store location:

export dockerRegistry=<registry-hostname>
export dockerRegistryPort=<port>

curl -v https://${dockerRegistry}:${dockerRegistryPort}/ 2>&1 \
    | grep CAfile \
    | cut -d":" -f2

Add certificate to trust store:

echo | openssl s_client -connect ${dockerRegistry}:${dockerRegistryPort} -showcerts \
    2>/dev/null </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' \
    >> /etc/ssl/certs/ca-certificates.crt

Login to Registry

If authentication is enabled:

Using curl:

curl -u <username>:<password> https://<registry>:<port>/v2/_catalog

Using Docker:

docker login <registry>:<port>

Push Images to Registry

Using Docker

Pull image:

docker pull docker.io/busybox:latest

Tag image:

docker tag docker.io/busybox:latest <registry>:<port>/busybox:latest

Push image:

docker push <registry>:<port>/busybox:latest

Using containerd

Pull image:

ctr -n k8s.io i pull docker.io/library/busybox:latest

Tag image:

ctr -n k8s.io i tag docker.io/library/busybox:latest <registry>:<port>/busybox:latest

Push image:

ctr -n k8s.io i push <registry>:<port>/busybox:latest -u <username>:<password>

Pull Images from Registry

Using Docker

docker pull <registry>:<port>/busybox:latest

Using containerd

ctr -n k8s.io i pull <registry>:<port>/busybox:latest -u <username>:<password>

Update Registry Credentials

To update Docker registry credentials in the Traceable Platform:

Step 1: Save Credentials

  1. Login to Traceable Installer
  2. Select the correct cluster name from the dropdown
  3. Navigate to Cluster Info
  4. Update:
    • IMAGE REGISTRY USERNAME
    • IMAGE REGISTRY PASSWORD

Step 2: Apply Credentials

  1. Navigate to Install Workflowcreate_regcred
  2. Click Apply
  3. Verify no error messages appear at the bottom of the screen

Verification

Check Registry Health

curl -k https://<registry>:<port>/v2/

Expected response: {}

List Repositories

curl -k https://<registry>:<port>/v2/_catalog

List Image Tags

curl -k https://<registry>:<port>/v2/<image-name>/tags/list

Troubleshooting

Certificate Errors

Symptoms: x509: certificate signed by unknown authority

Solutions:

  1. Add certificate to client trust store
  2. Use --insecure-registry flag (not recommended for production)
  3. Verify certificate SAN includes registry hostname

Authentication Failed

Symptoms: 401 Unauthorized

Solutions:

  1. Verify username and password
  2. Check htpasswd file is correctly mounted
  3. Regenerate htpasswd file if needed

Push/Pull Timeout

Symptoms: Operations timeout or hang

Solutions:

  1. Check network connectivity
  2. Verify firewall rules
  3. Check registry storage capacity
  4. Increase Docker timeout settings

Understanding Registry Host Options

When performing the installation, you are presented with several registry configuration options:

Available Options

Option Description
--registry-host The hostname of the docker image registry (e.g., docker.io). The original image host will be used if explicitly set to an empty string.
--registry-prefix The path prefix for the docker registry. Default value is empty string "". If provided, all images need to be in the same namespace.
--registry-mono-repo Use this flag only when all images are uploaded to a single repo within the docker registry. If no prefix is provided, it will use the namespace as the image name. If a prefix is provided, it will use the prefix as the image name.

Registry Configuration Examples

The following table shows the output with different combinations:

registry-host registry-prefix mono-repo Output
example.com "" N/A example.com/hypertrace/schema-registry:0.3.8 example.com/traceable/tiw-airgap:1.14.0
example.com "ces" N/A example.com/ces/schema-registry:0.3.8 example.com/ces/tiw-airgap:1.14.0
example.com "ces" true example.com/ces:schema-registry-tv-0.3.8 example.com/ces:tiw-airgap-tv-1.14.0
example.com "" true example.com/hypertrace:schema-registry-tv-0.3.8 example.com/traceable:tiw-airgap-tv-1.14.0
example.com/namespace "" N/A example.com/namespace/hypertrace/schema-registry:0.3.8 example.com/namespace/traceable/tiw-airgap:1.14.0
example.com/namespace ces N/A example.com/namespace/ces/schema-registry:0.3.8 example.com/namespace/ces/tiw-airgap:1.14.0
example.com/namespace ces true example.com/namespace/ces:schema-registry-tv-0.3.8 example.com/namespace/ces:tiw-airgap-tv-1.14.0
example.com/namespace "" true example.com/namespace/hypertrace:schema-registry-tv-0.3.8 example.com/namespace/traceable:tiw-airgap-tv-1.14.0
example.com/namespace "ces/us" N/A example.com/namespace/ces/us/schema-registry:0.3.8 example.com/namespace/ces/us/tiw-airgap:1.14.0
example.com/namespace "ces/us" true example.com/namespace/ces/us:schema-registry-tv-0.3.8 example.com/namespace/ces/us:tiw-airgap-tv-1.14.0


Support

For registry assistance, contact: support@harness.io

Provide the following information:

  • Registry deployment method
  • Error messages
  • Client configuration
  • Network topology