How to set up a private docker registry on Debian 11

Docker Registry is a stateless, highly scalable server-side application that stores and lets you distribute Docker images.

Step 1. Installing and configuring the docker registry

Docker Registry is an application with multiple components, so you will use Docker Compose to manage it. To start an instance of the registry, you’ll set up a docker-compose.yml file to define it and the location on the disk where your registry will store its data.
You’ll store the configuration in a docker-registry directory on the host server. Create it by running:

mkdir ~/docker-registry

Navigate to it:

cd ~/docker-registry

Then, create a subdirectory called data, where your registry will store its images:

mkdir data

Create and open a file called docker-compose.yml by running:

nano docker-compose.yml

Add the following lines, which define a primary instance of a Docker Registry:

version: '3'

    image: registry:latest
    - "5000:5000"
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
      - ./auth:/auth
      - ./data:/data
    restart: always

In our docker-compose.yml file, we see several lines of code. In the section services, we define our services. In this example, we have only one service named registry. For the registry service, we are using the latest image version. Under the ports, we map port 5000 on the host to port 5000 of the container, allowing us to send a request to 5000 on the server and have the request forwarded to the docker registry. The environment section defines where we will store the docker registry data. The docker registry data store the information on the host’s file system.

Hint: How to protect your private docker registry.
With this command, you can create HTTP Authentication for the sites it manages, which you can use to limit access to your docker registry.

htpasswd -Bc ~/docker-registry/auth/registry.password username

Save and close the file.

You can now start the configuration by running:

docker compose up -d

Step 2. Setting up nginx port forwarding

As part of the prerequisites, you enabled HTTPS at your domain. To expose your secured Docker Registry there, you must configure Nginx to forward traffic from your domain to the registry container.
You have already set up the /etc/nginx/sites-available/your_domain file containing your server configuration. Open it for editing by running:

nano /etc/nginx/sites-available/your_domain

Find the existing location block and change into this one:

location / {
    # Do not allow connections from docker 1.5 and earlier
    # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
    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;

Save and close the file when you’re done. Apply the changes by restarting Nginx:

systemctl restart nginx

If you receive an error message, double-check the configuration you’ve added.
To confirm that Nginx is properly forwarding traffic to your registry container on port 5000, run it:

docker compose up -d

Then, in a browser window, navigate to your domain and access the v2 endpoint like so:


The browser will load an empty JSON object:


Step 3. Increasing file upload size for Nginx

Before you can push an image to the registry, you need to ensure that your registry can handle large file uploads. The default size limit of file uploads in Nginx is 1 MB, which is insufficient for Docker images. To raise it, you’ll modify the main Nginx config file located at /etc/nginx/nginx.conf.
Open it for editing:

nano /etc/nginx/nginx.conf

Add the highlighted line to the http section:

http {
        client_max_body_size 16384m;

The client_max_body_size parameter is now set to 16384m, making the maximum upload size equal to 16GB.
Save and close the file.
Restart Nginx to apply the configuration changes:

systemctl restart nginx

In this step, you updated the file size allowed by Nginx. You can now upload large images to your Docker Registry without Nginx blocking the transfer or erroring out.