Add Registry To Docker

Add Registry To Docker

Reading time1 min
#Docker#Containers#DevOps#PrivateRegistry#ContainerSecurity#ImageManagement

Add Registry To Docker: Secure Image Management for Real-World Production

Network disruptions. Compliance audits. That day when Docker Hub rate limits throttle your CI pipeline mid-release. Relying on public registries introduces friction and risk into containerized workflows. For teams managing proprietary code or bound by regulatory restrictions, a private image registry quickly shifts from a luxury to a necessity.

Below: direct, pragmatic guidance for integrating a private Docker registry, with a focus on controlled image distribution, privilege management, and practical trade-offs. Commands and configurations shown assume Docker 24.x, but the patterns have held since at least 1.12.


Use Cases: Why Private Registries Matter

  • Layered access control: Prevents leaking sensitive base or application images.
  • Reduced latency, higher reliability: Images travel a shorter, internal path—crucial for multi-stage builds in CI/CD (see diagram below).
  • Metadata and audit: Tagging for compliance and traceability, not available with anonymous pulls from Docker Hub.
  • Highly available roots of trust: Public registry outages no longer block deployments.
[CI/CD runner] ---LAN---> [Private Registry] ---LAN---> [Prod Node]
         \                             /
      [Internet] <--X-- [Docker Hub] (fallback, as policy)

Minimal Local Registry: Start Small, Scale Later

Docker's reference registry (registry:2) spins up with a single command—suitable for initial testing or controlled development.

docker run -d \
    -p 5000:5000 \
    --restart=always \
    --name registry \
    registry:2.8.2

Expected logs:

time="2024-03-31T08:20:12Z" level=info msg="listening on [::]:5000" 

Note: No built-in TLS or authentication. Never expose such a containerized registry to anything outside a dev subnet.


Tagging: Proper Image Paths Prevent Future Ambiguity

You must push images to the registry with the correct repository prefix. Example below assumes you're working on a microservice named wallet-api:

docker tag wallet-api:1.3.5 localhost:5000/finops/wallet-api:1.3.5
  • Use a hierarchy (finops/wallet-api) if you plan for multiple projects.

Pushing and Pulling: Diagnostics and Gotchas

Pushing:

docker push localhost:5000/finops/wallet-api:1.3.5

Known issue: If Docker reports received unexpected HTTP status: 500 Internal Server Error, check disk usage on the host (docker system df and df -h). The registry container halts on full disk, but doesn't always emit clear errors.

Pulling elsewhere:

docker pull localhost:5000/finops/wallet-api:1.3.5

If you see Error response from daemon: Get https://localhost:5000/v2/ : http: server gave HTTP response to HTTPS client—see next section.


Securing the Registry: TLS and Authentication

By default, Docker CLI insists on HTTPS. For prod, terminating TLS at the registry container itself reduces MITM risk:

  1. Generate or provision certificates (LetsEncrypt, internal CA, or openssl self-signed for dev).

  2. Prepare HTTP Basic Auth credentials:

    docker run --rm --entrypoint htpasswd \
      httpd:2.4.58-alpine -Bbn ci-bot s3cr3tP4ss > ./auth/htpasswd
    
  3. Launch secured registry:

    docker run -d \
      -p 5000:5000 \
      --restart=always \
      --name registry \
      -v $PWD/auth:/auth \
      -v $PWD/certs:/certs \
      -e "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt" \
      -e "REGISTRY_HTTP_TLS_KEY=/certs/domain.key" \
      -e "REGISTRY_AUTH=htpasswd" \
      -e "REGISTRY_AUTH_HTPASSWD_REALM=RegistryRealm" \
      -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
      registry:2.8.2
    
  4. Authenticate docker clients (once per session/token validity):

    docker login localhost:5000
    

    Enter credentials as prompted.

Side note: For wider orgs, LDAP/OAuth integration is possible; official Docker registry supports additional auth backends if you mount a custom config.


Temporary Workaround: Insecure Registries in Dev

For isolated dev or CI runners, allow plain HTTP (skip for prod—intercepting credentials becomes trivial). Edit /etc/docker/daemon.json:

{
  "insecure-registries": ["localhost:5000"]
}

Restart Docker:

sudo systemctl restart docker

Known caveat: Some cloud-managed Docker environments (ECS, GKE, etc.) require different approaches—Daemon flags managed via UI or node group templates.


Registry Hygiene: Retention, Tagging, and Storage

Over time, storage bloat is inevitable; Docker's registry does not prune untagged layers by default.

  • Garbage collection:

    docker exec registry registry garbage-collect /etc/docker/registry/config.yml
    

    Downside: Requires downtime unless mirror/HA setup.

  • Immutable tags: Consider wallet-api:sha256-<digest> to avoid accidental overwrites. Harbor and Nexus support tag immutability policies natively—Docker registry does not.

  • S3/NFS backends: For durability, configure registry to store blobs on an object store (REGISTRY_STORAGE=s3) or NFS share—default local filesystem fails over poorly on bare metal if the host dies.


Managing Multiple Registries and Automated Workflows

CI/CD pipelines often need to interact with several registries (private, public, airgapped). Table below illustrates tagging and reference conventions:

Registry URLExample TagAuth?
docker.ionginx:1.25.2-alpineOptional
localhost:5000localhost:5000/finops/wallet-api:1.3.5Yes
registry.corp.local:443registry.corp.local/proj/frontend:20240601Yes

Automate login via docker-credential-helpers, or inject secrets into your pipeline runners (e.g., GitLab CI, Jenkins, or Github Actions using service containers).


Non-Obvious Tip: Airgapped Updates

When updating the registry image itself behind firewalls:

  • Export on a vendor-approved laptop: docker save registry:2.8.2 > registry.tar
  • Transfer via removable media; import with docker load < registry.tar. Never pull directly over prod network.

Summary

Private registries are not a panacea, but enable granular transport, audit trails, and resilience not feasible with public image sources. Start with a secured local registry; evolve towards high availability and directory-based access as organizational scale increases.

Gotcha: Cleaning up old blobs is easy to neglect—script it early, or prepare for disk alarms mid-release cycle.

For larger clusters or full artifact governance, investigate Harbor or JFrog Artifactory as managed solutions with built-in UI, RBAC, and vulnerability scanning.