Building a Private Docker Registry with Proxy Functionality Using Harbor
Preface
At some unknown point in time (actually, I can't remember), servers in mainland China lost the ability to directly connect to Docker Hub (docker.io). This was undoubtedly a blow to all mainland servers. Fortunately, proxy services have become increasingly available, so it's not completely unusable.
However, the GitHub-provided Docker image service ghcr.io, which shares the same plight as Docker Hub, has very few proxy services set up for it. Even if someone does set one up, accessing private repositories is impossible (basically due to login issues).
Because two of my projects use ghcr and are set to private, mainland servers couldn't pull them at all, or the pull was extremely slow. This made it impossible to use mainland servers for traffic distribution. I had been searching for a proxy solution for ghcr for a long time, and just recently I stumbled upon Harbor, an enterprise-level private Docker registry, so I decided to try setting it up.
EP0: Prerequisites
Server Configuration
First, you need:
- A server, preferably Linux, definitely not Windows
- An SSH remote tool, such as Termius, Tabby, or XShell (can be ignored for local deployment)
- A domain name (recommended). If deploying in mainland China and using a domain name, please complete ICP registration in advance.
Harbor is a program that runs on Docker, so Docker needs to be installed on the server in advance. If the server is in mainland China, you also need to configure a proxy in advance; otherwise, subsequent steps will fail. For this, you have the following options:
Download the Installation Package
Open Harbor Releases. You will see something like the following in the Releases section:

harbor-offline-installer-v<version>.tgz is the offline installation package, and harbor-online-installer-v<version>.tgz is the online installation package. Please deploy based on the actual latest version.
This tutorial uses the online version. If your server absolutely cannot connect to Docker Hub, please use the offline version. There is no difference in usage between the two; the difference is that the online installer pulls the image from Docker Hub before deployment, which is relatively lighter and leaves the local files cleaner.
Download the file to the server and extract it. A folder named harbor will appear.
Enter the harbor folder. If the directory contains the following files (and none are missing), then we have completed the first step.

All files
EP1: Configuration
Rename harbor.yml.tmpl to harbor.yml
Copy harbor.yml.tmpl and rename it to harbor.yml. Do not directly modify the file name to avoid serious consequences from accidentally deleting content.
cp harbor.yml.tmpl harbor.yml
Change the Password
Enter harbor.yml:
vim harbor.yml
Find harbor_admin_password:

Change Harbor12345 to a different string. Remember this string; it will become the initial password for the Admin account when logging into the web console later.
At the same time, it is recommended to also change database.password to another string (as shown in the image below). This string will become the access password for the database that Harbor will deploy later, but you don't need to remember it.

Change the Access Address
At the top of harbor.yml, find hostname:

Modify hostname to the actual access address. This does not have to be a domain name; you can use the server's IP address.
Configure Ports
Based on various reasons, there are generally three scenarios:
Save harbor.yml
After completing the above configuration, press esc, type :wq, and the modification of harbor.yml is complete.
EP2: Start the Installation Script
Run the following command in the terminal:
bash install.sh
This will start the installation process.
When Harbor has been installed and started successfully. appears, the entire installation is complete.

At the same time, the entire service is up and running.
EP4: Access the Web Interface
||I can't count the number between 2 and 4||
Based on the hostname and port you configured, access your Harbor in a browser.
You will then see the following interface:

Log in. The username for the initial account (or Admin account) is admin, and the password is the harbor_admin_password you set earlier.
After logging in, you will see the following interface:

At this point, it is confirmed that the entire Harbor service is running normally.
EP5: Security Operations
Change the Admin Account Password
Although the default password was already changed in harbor.yml, for security reasons, it is still recommended to change the password once on the web interface.
Click on the user icon in the top right corner, then click Change Password. Fill in all required fields in the pop-up form.

Create a New User
Although creating a new user is not strictly necessary, for security reasons, I still recommend creating a new user specifically for logging into your account from Docker.
Click on User Management on the left, then click Create User. Fill in all required fields in the pop-up form.

EP6: Logging in from Docker
Enter the following command in the terminal:
docker login <hostname>:<port>
An interactive prompt will appear:

First, enter Username (the username you set when creating the user), press Enter. Then enter Password (the password you set when creating the user; the entered password will not be displayed), and press Enter.
If the credentials are correct, the following will appear:

At this point, your server is connected to your Harbor, and all push and pull operations (including private repositories) are smooth.
EP-S-1: Configuring the Proxy
Associate with Other Services
After logging into your Harbor web interface, click on Registries on the left side of the page, then click New Endpoint.

The New Endpoint window will pop up.
Adjust the Provider option; you will see 12 options.

If you select harbor or Docker Registry, you need to fill in the address of the corresponding service (i.e., Endpoint URL). If you select any other option, you do not need to fill in the service address.
Here, we use GitHub GHCR as an example (not Google GCR; be careful, the addresses differ by only one letter).

(For information on how to obtain GitHub access credentials, please visit https://github.com/settings/tokens.)
After configuration, click OK.
Set Up a Project
What is a "project"? In Harbor, a project is equivalent to a separate storage location. It points to where the images are stored. Access management (i.e., whether an image is public or private) is determined on a per-project basis, not per image. This is different from many Docker cloud services.
Click on Projects on the left side of the page, then click New Project.


Then click OK, and the project setup is complete.

END: Pulling an Image
Taking ghcr.io and the project name ghcr configured in the image above as an example, assume the original address is:
ghcr.io/NiuBoss123/114514:latest
After being proxied by Harbor, the address will become:
<hostname>:<port>/ghcr/NiuBoss123/114514:latest
That is, replace ghcr.io with <hostname>:<port>/ghcr.
Subsequent operations are identical to those with the original address.
Afterword
Isn't it overkill to set up Harbor just for a proxy? Personally, I think it is indeed overkill . But considering its status as an enterprise-level Docker registry, it shouldn't be surprising.meaning I just wanted to tinker with it
Some might ask why not use Docker Registry. Considering that it is essentially just a storage repository, with no web console, no proxy functionality, and requiring manual image uploads, it still feels quite troublesome (although using Harbor is just as troublesome, but using Harbor is a bit more clever ).is it really clever?
Related Links
- Harbor Official Website: goharbor.io
- Harbor GitHub Repository: goharbor/harbor
(No domain names were harmed in the writing of this tutorial.)