How To Setup Private Docker Hub
How To Setup Private Docker Hub
Get
6,000 build min/mth free! Learn more.
Hitesh Jethva
Table of Contents
This article outlines the key steps to setting up a Docker registry. Earthly
precisely optimizes Docker image build processes. Learn how.
On the other hand, a private registry provides central image management, cost-
saving, scanning capabilities, access control, support for external storage, and
more security features. With a private registry, you can define your own storage
location for all your images and set your own policies to prevent deploying
images that don’t meet your policy standard.
You have some choices when it comes to setting up a private registry. You could
use a third party service like Amazon ECR, or you can set up your own registry,
which is surprising easy to do.
In this step-by-step guide, you’ll learn how to set up your own private Docker
registry on Linux. But first, let’s take a closer look at Docker registries and the
difference between public and private registries.
Prerequisites
Two Ubuntu 22.04 servers. One for the Docker registry, and one to use as a
client machine where you will push and pull images.
First, you will need to install Docker and Docker Compose packages on both
servers.
Next, you’ll need to grab some dependencies to get packages over the secure
HTTPS connection.
Next, import the GPG key for Docker to install only authenticate package and add
Docker’s official repository to APT sources.
Since we’ve added a new software repository to apt, we’ll need to update again.
This command will install both Docker and Docker Compose packages to your
server, start the Docker service and enable it to start after the system reboot. You
can verify the Docker installation by executing the command given below.
Remember, you’ll need to run all of the above commands on both servers before moving
on to the next step.
1. Create a Docker Compose file that will be used to configure the private
registry.
3. Set up basic authentication to ensure that only authorized users can access
the registry server.
We’ll use Docker Compose to define all the components required for setting up a
private registry. Docker Compose makes it easy to define all the services we’ll
need as well as allow us to spin them all up with a single command.
Let’s start by creating a directory to store all configurations for the private registry.
cd ~/private-registry >_
nano docker-compose.yml
Add the following section to define the registry service and set the registry
image using the latest tag. The image directive downloads the latest version of
the registry Docker image from the Docker Hub public registry.
docker-compose.yml Copy
version: '3'
services:
registry:
image: registry:latest
Next, add the port section to map the host machine port 5000 to the container
port 5000 .
docker-compose.yml Copy
ports:
- "5000:5000"
Then, add the environment section where we will set up some environment
variable related to some basic authentication.
docker-compose.yml Copy
environment:
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry
REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /registry-data
Next, add the volumes section to bind the /auth and /registry-data directories
on the host file system to the container file system.
Docker volumes play an important role to persist data in Docker containers and
services. The registry-data volume will store all Docker images and registry
configuration information while the auth volume will store and persist all user’s
passwords. Later, we’ll also set up an HTTP authentication to ensure that only
authenticated users can access the registry.
docker-compose.yml Copy
volumes:
- ./auth:/auth
- ./registry-data:/registry-data
When you are finished, your final configuration file will look something like this:
docker-compose.yml Copy
version: '3'
services:
registry:
image: registry:latest
ports:
- "5000:5000"
environment:
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry
REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /registry-data
volumes:
- ./auth:/auth
- ./registry-data:/registry-data
NGINX is open-source and the most popular software that you can use as a web
server and reverse proxy. The Docker registry container is accessible only from
the local host. So we will need to install and configure NGINX to forward traffic
from the remote machine to the registry container running on port 5000 .
Let’s start by installing the nginx and apache2-utils packages on your server.
The apache2-utils package will download the htpasswd utility needed to set up
basic HTTP authentication.
Now, create an NGINX virtual server block to serve the Docker registry. Basically,
this is where we will define how NGINX should handle requests.
nano /etc/nginx/conf.d/registry.conf >_
First, add the listen directive to specify the NGINX listening port. Next, define
the server_name with your domain name. Finally, add the error and access log
path.
registry.conf Copy
server {
listen 80;
server_name private.linuxbuz.com;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
Next, in the location / section, set the proxy_pass directive to forward all
incoming traffic on domain private.linuxbuz.com to the localhost on registry
container port 5000 .
registry.conf Copy
location / {
if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$"
return 404;
}
proxy_pass http://localhost:5000;
proxy_set_header Host $http_host; # required for docker client's sake
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900;
}
}
Your final NGINX configuration file will look something like this:
registry.conf Copy
server {
listen 80;
server_name private.linuxbuz.com;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$"
return 404;
}
proxy_pass http://localhost:5000;
proxy_set_header Host $http_host; # required for docker client's sake
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900;
}
}
client_max_body_size : Sets the upload limit per file. By default, NGINX has
an upload limit of 1 MB per file. To allow larger image upload to the Docker
registry, you will need to define this value as per your requirement.
server name then you will get the error could not build the
server_names_hash, you should increase server_names_hash_bucket_size:
32
client_max_body_size 4000m;
server_names_hash_bucket_size 64;
You should see the NGINX running status in the below screenshot.
At this point, the NGINX web server is installed and configured to forward traffic
to the private registry server.
First, install the Certbot Let’s Encrypt client package to install and manage the
SSL certificate.
ln -s /snap/bin/certbot /usr/bin/certbot
Then, run the certbot command followed by your domain name to download the
SSL certificates, and configure NGINX to use the downloaded certificates for your
domain.
You will be asked to provide your real email address and accept the term of
service to finish the SSL installation.
Next, navigate to the auth directory and use the htpasswd command to create a
registry.password file. The htpasswd is a utility used to create a file to store
username and password information for Apache basic authentication.
cd ~/private-registry/auth >_
htpasswd -Bc registry.password adminuser
This command will download the registry docker container image and start the
container as shown below.
Run the following command to check the Docker registry container status.
docker-compose ps >_
This will show you the active status of the registry container.
Now, let’s test our new registry by creating a custom docker image on the client
server and pushing it to our newly created private registry. For demonstration, we
will create a custom Ubuntu image with the NGINX server installed on it.
First, pull the latest Ubuntu image from the Docker Hub registry.
docker pull ubuntu:latest >_
This will start the image and put you into the Ubuntu shell as shown below.
Next, update the Ubuntu repository and install the NGINX package inside the
container.
nginx -v >_
exit >_
This will create a new custom image named ubuntu22-image on your client
server.
You can verify the created image using the following command.
You should see your newly created image in the following screenshot.
At this point, you have created a custom image called ubuntu22-image on the
client server.
Now, you will need to upload this image from the client server to your private
docker registry so that users can download and reuse it.
First, use the docker login command on the client server to log in to your private
registry.
We will need credentials that we set up on the registry server to authenticate the
registry. After successfully authenticating to the registry. You should see the
following screen.
Login to registry server
Next, tag your custom Ubuntu image that matches your registry server domain
name.
Finally, run the docker push command to upload your custom Ubuntu image to
the private Docker Registry.
This will upload your custom image to the private registry server as shown below.
At this point, you have uploaded the custom Ubuntu image to your private registry
server.
Again, make sure you log into your private registry using the docker login
command.
Next, pull the Ubuntu image from the private registry to your client server.
After the successful download, you should see the following screen.
Now, run the docker run command to create a container from the downloaded
image.
This will start the container and put you into the container shell like before.
Run custom ubuntu image
nginx -v >_
Now, log out from the running container using the exit command.
exit >_
Conclusion
In this guide, we’ve covered how to establish a private Docker registry server on
Linux, including setting up basic authentication, enabling SSL, creating a custom
image, and verifying the registry server. Docker registry is crucial for secure
image storage and management in modern software development.
With the knowledge you’ve gained today, you’re now prepared to implement
security best practices for Docker containers and images in an enterprise setting.
If you’ve enjoyed setting up your own Docker registry and are interested in further
boosting your container build processes, take a peek at Earthly. It’s a tool that
can help optimize your builds with its unique features like reproducible, portable,
and parallel builds.
Subscribe
Learn how to setup and use Amazon's Elastic Container Registry (ECR) to store and
manage your container images. Discover the benefits of using ECR over Docke...