AWS Logo
Menu
Create a Docker registry

Create a Docker registry

Learn to create a Docker registry: Set up your own private registry to store, manage, and share Docker images securely within your organization.

Published Apr 4, 2025

👉 Public Registry:

To create a public Docker registry, you can use Docker Hub, which is the default public registry provided by Docker. Here’s how you can create a public repository on Docker Hub and push images to it:

Sign Up/Login to Docker Hub:

  • If you don’t already have a Docker Hub account, sign up at Docker Hub.
  • If you have an account, log in to Docker Hub.
You can use your Google or GitHub account to authenticate.

Create a Repository:

  • Once logged in, navigate to your Docker Hub account dashboard.
  • Select the Create repository button in the top-right corner.
  • Select your namespace (most likely your username) and enter docker-repo as the repository name.
  • Set the visibility to Public.
  • Select the Create button to create the repository.
That’s it. You’ve successfully created your first repository. 🎉
This repository is empty right now. You’ll now fix this by pushing an image to it.

Verify Repository :

  • After creating the repository, you’ll be redirected to the repository’s page on Docker Hub.
  • The URL for your repository will be in the format https://hub.docker.com/r/<your-docker-hub-username>/docker-repo.
  • You can verify that the repository has been created and is set to public access.

👉 Private Registry:

Docker provides its own image named registry for this purpose. We need to pull this image and run a container using this image.
  • -d runs the container in detached mode (in the background).
  • -p 5000:5000 maps port 5000 on the host to port 5000 in the container. This is the default port used by the Docker Registry.
  • --name my-registry assigns the name my-registry to the container.
  • registry specifies the Docker image (registry) to use for the container.
In the above command, we are running the container using the registry image, we have provided a name for the container and a port. By default it listens on port 5000 and also we have not assigned any volume in this command, a volume will be created automatically by default.

Verify Container Status:

After running the container, you can verify its status by using the docker container ls command:
This command lists all running Docker containers. You should see the my-registry container listed.

Access the Docker Registry (Optional):

  • If you want to access the Docker Registry running in the container, you can use tools like curl or Docker CLI commands.
  • For example, you can check if the registry is running by using curl:\
This command sends a GET request to the Docker Registry’s API endpoint (/v2/) to verify its availability.
As you can see,there is no image present currently. Now we will add an image to this registry.
First let us inspect our container and check the volume attached to our container.

Inspect the Docker Container:

Use the docker inspect command followed by the container name (my-registry in this case) to inspect the container:
We can see the output of the inspect command and find the volume information in the format shown in the above output.
In case if our container stops by any chance and we want to run the container again then we can attach the same volume to the container using the above volume information.
Also notice that the driver in the above volume information is ‘local’ because our data will be stored on the local file system, there are also drivers available for remote cloud storage as well which we can use to store our data remotely such as AWS S3, Google Cloud, Azure etc.
Now coming back to pushing an image to the local registry.
We will be pushing the redis image to the local registry.

Tag the Redis Image with Registry URL:

Tag the Redis image with the URL of your local Docker Registry (localhost:5000 by default)
As seen in the below image our image with the local registry tag is created.

Push the Tagged Redis Image to Local Registry:

The image is pushed. Now let’s verify if the image is pushed successfully or not. For verifying, curl to http://localhost:5000/v2_catalog, we see that our image has been pushed successfully.

Delete the Redis Image:

Once you’ve identified the Redis image, use the docker image rm command to delete it.
If we disconnect our internet and try to pull the same image again, we get the error as the default registry is unreachable.
But we are able to download the image from the local registry.

Pull Image from Local Registry:

To pull an image from your local Docker Registry, use the docker pull command with the full registry URL and image name.
We can Replace localhost:5000/redis:latest with the appropriate registry URL, image name, and tag that you used when pushing the Redis image to your local registry.
Note — A point to note here is that docker only allows secure registry which are secured using TLS with the exception of localhost.
Docker by default requires secure connections (TLS) for accessing Docker registries, except for registries accessed locally via localhost. This security measure helps protect sensitive data and ensures that communication between Docker clients and registries is encrypted and authenticated.
When Docker clients communicate with a Docker registry over a network (e.g., Docker Hub, private registries hosted on remote servers), the registry URL must use the HTTPS protocol (https://) and have a valid TLS certificate. This ensures that data transferred between the client and registry is secure and protected against unauthorized access or tampering.
To check this let us tag another image to the IP allotted to our local machine.
For example, to tag an image named myimage with tag latest to the IP address 192.168.1.100 and port 5000, you would use:

Push or Use the Tagged Image:

you’re encountering an error when trying to push an image to a Docker registry using HTTP instead of HTTPS. Docker requires secure connections (HTTPS) for interacting with remote registries by default to ensure data security and integrity.
To resolve this issue and push your image to a Docker registry, you’ll need to use HTTPS instead of HTTP in the registry URL. Here’s how you can do it:
To allow get the docker to allow insecure location, we need to modify docker configuration to allow insecure registries or locations, including specific IPs, you need to create or edit the daemon.json file. This file is typically located in /etc/docker/ directory on Linux systems. Here's how you can create the daemon.json file and specify insecure registries or IP addresses:
Use a text editor (e.g., nano, vi, vim) to create or edit the daemon.json file
Inside the daemon.json file, add a JSON configuration to specify the insecure registry or IP address that Docker should allow connections to.
After adding the configuration, save the changes and close the text editor.
vi or vim: Press Esc to exit editing mode, then type :wq to save and quit, and press Enter

Restart Docker Daemon:

After modifying the daemon.json file, restart the Docker daemon to apply the changes:
Now Start the Containers:

Push the Tagged Image to Insecure Registry:

you can push it to the registry using the docker push command.
  • After pushing the image, you can verify that it was successfully pushed to the insecure registry by checking the output of the docker push command or using the Docker CLI to list images in the registry.
  • Additionally, you can verify the image’s presence in the insecure registry by inspecting the registry’s catalog or using Docker commands specific to managing images in the registry.

👉 Docker Registry/Repository (Secure):

For making our registry secure we will need certificates. So let’s create a directory first to store those certificates. And then we will generate self-signed certificates using OpenSSL.
Here’s how you can create a directory to store certificates and generate self-signed certificates using OpenSSL for securing your Docker registry:

Create a Directory for Certificates:

Create a directory to store your certificates. You can choose a suitable location, such as /etc/docker/certs/:
Navigate to the newly created directory:

Generate Self-Signed Certificates with OpenSSL:

Use OpenSSL to generate a private key and a self-signed certificate for your Docker registry. Replace registry.example.com with your registry's domain name or IP address:
The command you provided generates a self-signed SSL certificate using OpenSSL with the following options:
  • req: Indicates that this command is for creating a new certificate signing request (CSR) and a new private key.
  • -newkey rsa:4096: Specifies the type of key to be generated (rsa:4096 indicates an RSA key with a key length of 4096 bits).
  • -nodes: Specifies that the private key should not be encrypted with a passphrase (this is not recommended for production environments but can be useful for testing or development).
  • -sha256: Specifies the hashing algorithm to use for the certificate signing request (CSR) and the self-signed certificate. In this case, SHA-256 will be used.
  • -keyout certs/domain.key: Specifies the output file (domain.key) for the private key.
  • -x509: Specifies that a self-signed certificate should be generated (as opposed to a certificate signing request for submission to a certificate authority).
  • -days 365: Specifies the validity period of the self-signed certificate in days (365 days in this case).
  • -out certs/domain.crt: Specifies the output file (domain.crt) for the self-signed certificate.
After running this command, you will have two files in the certs/ directory:
  1. domain.key: The private key file (not encrypted in this case due to the -nodes option).
  2. domain.crt: The self-signed SSL certificate file.
We need to copy the generated self-signed SSL certificate (domain.crt) to the specified path (/etc/docker/certs.d/repo.docker.local:5000/ca.crt), you can use the cp command in the terminal. Here's how you can do it:
First, create the directory structure required by Docker for storing SSL certificates.
Next, copy the generated self-signed certificate (domain.crt) to the appropriate directory and rename it as ca.crt (the naming convention Docker expects for the CA certificate).
After copying the certificate we need to restart the docker service.
And we also need to run the registry again using the command in the below image.
In the above command we are running the container named secure_registry along with that we have provided parameters to map the port, using -v flag we are mounting the certificate present in /home/certs directory to the certs folder inside the container and we are passing environment variables using -e flag for passing the path to the self-signed certificate and the generated key present inside the container.
So our registry is up and running now.
Let’s try to push an image to the registry again to the insecure registry. This gives an error message.
Now let’s try to push an image to the domain name ‘repo.docker.local’ for which we generated the self-signed certificate.
But again on trying to push this image we get an error which says docker is unable to resolve this domain name.
To resolve the issue of Docker being unable to resolve the domain name repo.docker.local, you can indeed add an entry to your /etc/hosts file. This step is particularly useful for testing and development environments where you want to map domain names to specific IP addresses manually. Here's how you can do it:
Add a new line at the end of the file to map repo.docker.local to the correct IP address. Replace <IP-address> with the actual IP address of your Docker registry:
Save the changes to the /etc/hosts file and exit the text editor.
After updating the hosts file, restart the Docker service to apply the changes:
Now let’s again try to push the image.
The image is pushed and we have set up our secure register successfully!
 

Comments