Building a Mirror Docker Registry

Sometimes when browsing Docker.io, I come across popular projects that I would like to experiment with. However, I often find that these projects have been deleted. This prompted me to think about setting up a mirror docker registry, so that I can directly store interesting projects in my own registry for future use.

TOC

  1. Setting up a Docker.io Mirror Registry
  2. Client Operations in a Linux Environment
  3. Setting up a Microsoft Artifact Registry
  4. Client Operations in a Windows Environment
  5. Setting up an Azure Container Registry
  6. Client Operations in a Mac OS Environment
  7. Handling Routing Issues
  8. Managing the Docker Registry

Setting up a Docker.io Mirror Registry

I use Ubuntu Server 22.04 as the Mirror Registry. Since a docker registry is also a docker container, you need to first install the Docker daemon on your server. Please refer to these two documents for installation instructions.

https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-22-04

https://www.digitalocean.com/community/tutorials/how-to-set-up-a-private-docker-registry-on-ubuntu-22-04

Next, create a directory to store the actual mirror stuff. Please note that a Docker Registry can only mirror services under a single domain. Let’s take docker.io as an example.

cd ~/
mkdir -p dr-docker-5000/data

Create a configuration yml file.

vi dr-docker-5000/docker-compose.yml

version: '3'

services:
  registry:
    restart: always
    image: registry:latest
    ports:
    - "5000:5000"
    environment:
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
      REGISTRY_PROXY_REMOTEURL: https://registry-1.docker.io
    volumes:
      - ./data:/data

Launch this container.

cd ~/dr-docker-5000/
docker compose up -d

And that’s it, we have completed the setup. Now let’s take a look at how to use it.

Client Operations in a Linux Environment

The most common Docker projects are usually built in a Linux environment. Therefore, let’s start by simulating the operations of the end user in a Linux environment.

I use Ubuntu Server 22.04 as the end user client part. First, you need to create the file /etc/docker/daemon.json with root privileges. Please be noticed that “10.10.10.19” is the LAN IP from the mirror docker registry.

vi /etc/docker/daemon.json

{
  "insecure-registries": [
    "10.10.10.19:5000"
  ],
  "registry-mirrors": [
    "http://10.10.10.19:5000"
  ]
}

Then, edit the Docker service configuration file /usr/lib/systemd/system/docker.service and append “–config-file /etc/docker/daemon.json” at the end of the “ExecStart” line.

vi /usr/lib/systemd/system/docker.service

Once you have made the changes, save the file and restart the Docker service.

systemctl daemon-reload
systemctl restart docker

Now we can start pulling the project from docker.io.

docker pull 10.10.10.19:5000/library/hello-world:latest

The endpoint mentioned above is divided into three parts. The “10.10.10.19:5000” represents that we are accessing it through the mirrored Docker registry. “library” is a fixed route reserved by Docker.io, and we will explain it in detail in the following chapters. Finally, “hello-world:latest” is the project name and tag that you see on Docker.

Previously, the pull syntax only included “hello-world:latest”, but now it should be “10.10.10.19:5000/library/hello-world:latest”.

Setting up a Microsoft Artifact Registry

Let’s take Microsoft Artifact Registry as an example. Now, there are also increasing numbers of Docker projects that belong to the Windows operating system. Windows projects tend to be larger in size, and having a mirror registry eliminates the need to spend a lot of time pulling images every time.

cd ~/
mkdir -p dr-mcr-5001/data

Create a configuration yml file.

vi dr-mcr-5001/docker-compose.yml

version: '3'

services:
  registry:
    restart: always
    image: registry:latest
    ports:
    - "5001:5000"
    environment:
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
      REGISTRY_PROXY_REMOTEURL: https://mcr.microsoft.com
    volumes:
      - ./data:/data

Launch this container.

cd ~/dr-mcr-5001/
docker compose up -d

And that’s it.

Client Operations in a Windows Environment

To use Docker images in a Windows environment, you need to have Docker Desktop installed with the Windows Docker daemon. Therefore, let’s simulate the operations of an end user in a Windows 11 environment.

First, open Docker Desktop, then click on the gear icon (Settings) in the upper right corner. Select “Docker Engine” on the left side. In the appropriate section, add the following content. Finally, click on “Apply & Restart” to save the changes and restart Docker.

  "insecure-registries": [
    "10.10.10.19:5001"
  ],
  "registry-mirrors": [
    "http://10.10.10.19:5001"
  ]

Now we can start pulling the project from Microsoft Artifact Registry.

docker pull 10.10.10.19:5001/windows/nanoserver:ltsc2022

Setting up an Azure Container Registry

Let’s take Azure Container Registry as an example of a private registry. It can be used to mirror images that require login authorization. This time, let’s simulate the operations of an end user in a Mac OS environment.

cd ~/
mkdir -p dr-cchlabacr-5002/data

Create a configuration yml file.

vi dr-cchlabacr-5002/docker-compose.yml

version: '3'

services:
  registry:
    restart: always
    image: registry:latest
    ports:
    - "5002:5000"
    environment:
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
      REGISTRY_PROXY_REMOTEURL: https://<your-acr-name>.azurecr.io
      REGISTRY_PROXY_USERNAME: <your-acr-user>
      REGISTRY_PROXY_PASSWORD: <your-acr-pass>
    volumes:
      - ./data:/data

Which the information from <your-acr-name> and <your-acr-user> and <your-acr-pass> could be located here:

Launch this container.

cd ~/dr-cchlabacr-5002/
docker compose up -d

And that’s it.

Client Operations in a Mac OS Environment

We will use Mac OS X as the operating system. First, open Docker Desktop, then click on the gear icon (Settings) in the upper right corner. Select “Docker Engine” on the left side. In the appropriate section, add the following content. Finally, click on “Apply & Restart” to save the changes and restart Docker.

  "insecure-registries": [
    "10.10.10.19:5002"
  ],
  "registry-mirrors": [
    "http://10.10.10.19:5002"
  ]

Now we can start pulling the project from Azure Container Registry.

docker pull 10.10.10.19:5002/hello-world:latest

Handling Routing Issues

Look into these commands:

docker pull 10.10.10.19:5000/library/hello-world:latest
docker pull 10.10.10.19:5001/windows/nanoserver:ltsc2022
docker pull 10.10.10.19:5002/hello-world:latest

The original command without using mirror registry should be like:

docker pull hello-world:latest
docker pull mcr.microsoft.com/windows/nanoserver:ltsc2022
docker pull .azurecr.io/hello-world:latest

Command 1: Docker is a product of Docker.io, so by default it searches the website https://registry-1.docker.io. You don’t need to explicitly mention it. The reason we have the route named “library” is because different registry implementations in different companies have different routing methods. “library” is a standard that many people use, so if you need to use a proxy server to assist with the requests, you need to add it.

Command 2: From experimentation, using both “10.10.10.19:5001/library/windows/nanoserver:ltsc2022” and “10.10.10.19:5001/windows/nanoserver:ltsc2022” works. Therefore, if you encounter a “manifest unknown” error in the future, you can try both options.

Command 3: From experimentation, it has been found that Azure Container Registry (ACR) does not support the commonly used “library” route. Therefore, when making requests, you should exclude the “library” route.

Managing the Docker Registry

When the number of mirrored projects increases, it becomes necessary to manage them in GUI mode. Fortunately, there are mature solutions available for this requirement. Let’s go back to the mirrored server from the beginning and proceed with the installation process.

cd ~/
mkdir dr-ui-4999
vi dr-ui-4999/docker-compose.yml

version: '3'

services:
  registry-ui:
    restart: always
    image: joxit/docker-registry-ui:latest
    ports:
    - "4999:80"
    environment:
      SINGLE_REGISTRY: false
      CATALOG_ELEMENTS_LIMIT: 1000

cd ~/dr-ui-4999/
docker compose up -d

To avoid CORS (Cross-Origin Resource Sharing) issues, the original three registries need additional configuration settings.

# Step 1 (choose one of them)
docker exec -it dr-docker-5000-registry-1 /bin/sh
docker exec -it dr-mcr-5001-registry-1 /bin/sh
docker exec -it dr-cchlabacr-5002-registry-1 /bin/sh

# Step 2
vi /etc/docker/registry/config.yml

vi /etc/docker/registry/config.yml

# Rewrite the http section like this
http:
  addr: :5000
  headers:
    X-Content-Type-Options: [nosniff]
    Access-Control-Allow-Origin: ['*']
    Access-Control-Allow-Methods: ['*']
    Access-Control-Allow-Headers: ['Authorization', 'Accept']
    Access-Control-Max-Age: [1728000]
    Access-Control-Allow-Credentials: [true]
    Access-Control-Expose-Headers: ['Docker-Content-Digest']

And that’s it. We could now accessing the management page via http://10.10.10.19:4999

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *