Nexus Proxy Docker Repository with Nginx and Traefik

In this article, we will explore the use of proxy configurations in Nexus, a container image registry solution that provides critical benefits for environments with restricted access to external resources. The primary use case for employing a proxy Docker image repository is evident in scenarios such as having Kubernetes clusters operating in a closed network. Under such circumstances, direct access to external Docker images is not possible. By setting up a Nexus repository to proxy these external sources, you can cache Docker images locally, ensuring uninterrupted access even if the external servers experience downtime or are otherwise unavailable. This setup not only mitigates the risk of dependency on external sources but also significantly enhances the security and efficiency of managing Docker images in isolated environments.
Throughout the article, we will set up two Nexus instances on different VMs. One will employ Nginx as a reverse proxy, while the other will use Traefik. We will obtain our SSL certificate from Let’s Encrypt using Certbot.

As a prerequisite, Docker and Docker-compose must be installed on the VMs. Additionally, a domain for entering DNS records is required.

In the first Nexus setup we will establish with Nginx, there will be two Docker repositories:

  1. A proxy repository at the / path for DockerHub.
  2. A hosted repository at the /hosted path for local Docker images.

In the second Nexus setup we will establish with Traefik, there will be two proxy-type repositories:

  1. A proxy repository at the / path for DockerHub.
  2. Another proxy at the /hosted path targeting the first Nexus setup with Nginx. This configuration allows fetching images from Nginx’s hosted repository through Traefik.

First, let’s create the Nexus repository that we will use with Nginx. In this repository, we will create two image repositories. The first will be of the hosted type, allowing us to pull and push Docker images. The second will be a proxy type, which we will use to proxy DockerHub. Later, we will use the hosted repository we created as a proxy in the repository set up with Traefik.

We mentioned using Certbot to obtain the certificate, which requires a web server like Nginx or Apache. Therefore, I will initially install Nginx as a service to acquire the certificate. After obtaining the certificate, I will stop the Nginx service. Before obtaining the SSL certificate with Certbot, it’s crucial to remember to set up the DNS records for your domain names at your hosting provider. You can find more details in the link below.

sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl status nginx

sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

sudo certbot certonly --nginx -d nginx-nexus.sametustaoglu.com 
sudo systemctl stop nginx

The certificate files will be created in the /etc/letsencrypt/live/ directory. Let’s copy these files into a newly created certs folder in the home directory.

mkdir certs
sudo cp /etc/letsencrypt/live/nginx-nexus.sametustaoglu.com/fullchain.pem certs/
sudo cp /etc/letsencrypt/live/nginx-nexus.sametustaoglu.com/privkey.pem certs/
sudo chown -R ubuntu:ubuntu certs/

Now, let’s create our docker-compose file consisting of Nginx and Nexus images.

version: "3.3"
services:
  nginx:
    image: nginx:latest
    container_name: nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./config/nginx.conf:/etc/nginx/nginx.conf
      - ./certs:/etc/nginx/certs
  nexus:
    image: sonatype/nexus3:3.59.0
    container_name: nexus
    volumes:
        - ./nexus-data:/nexus-data

Let’s discuss our docker-compose file, which includes two services: one for Nginx and the other based on a Nexus image. We expose the Nginx container through port 443. The volumes for this container include the SSL certificates folder we created and the Nginx configuration file that we will create shortly. For the Nexus container, we create a volume named nexus-data in the current directory. After creating this folder, we will need to change its file permissions, and I’ll share the relevant command for that as well.

Let’s create a folder named config in the home directory and inside it, create a file named nginx.conf. The content of the file will be as follows.

events {
  worker_connections 1024; 

http {
  client_max_body_size 500M;
 
  server {
    listen 80;
    server_name nginx-nexus.sametustaoglu.com;
    return 301 https://$host$request_uri; 
  }

  server {
    listen 443 ssl; 
    server_name nginx-nexus.sametustaoglu.com;

    ssl_certificate /etc/nginx/certs/fullchain.pem; 
    ssl_certificate_key /etc/nginx/certs/privkey.pem;

    location / {
      proxy_pass http://nexus:8081; 
      proxy_set_header Host $host; 
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-Host $server_name;
    }
    location /v2 {
        proxy_pass http://nexus:8082; 
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $server_name;
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-Ssl on;
        proxy_buffering off;
        proxy_set_header Connection "";
    }
    location /v2/hosted {
        proxy_pass http://nexus:8083; 
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $server_name;
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-Ssl on;
        proxy_buffering off;
        proxy_set_header Connection "";
    }
  }
}

Let’s discuss the nginx.conf file and explain the key parts. It will listen on port 80, and if there is a request to nginx-nexus.sametustaoglu.com, it will redirect it to port 443. The / path will redirect to the Nexus homepage. The /hosted path will be for the Docker repository we will create of the hosted type, and /v2 will actually serve as the root path for this Docker repository, which we will use to proxy to DockerHub.

Use the command docker-compose up to start the services.

Here’s the command to set the necessary file permissions for the nexus-data volume I mentioned earlier:

sudo chmod 777 nexus-data/ 

To log in, visit the following URL: https://nginx-nexus.sametustaoglu.com/. The username is admin. To obtain the initial password, use the command cat nexus-data/admin.password on your server. After logging in, you will need to set a new password.

Following that, as per our scenario, create a proxy type image repository for DockerHub on port 8082 and a hosted type image repository on port 8083. These settings will configure Nexus to handle both local Docker image storage and caching images from DockerHub.

Now, from your local computer, use the following command to log in to your Nexus repository through Docker:

docker login nginx-nexus.sametustaoglu.com -u admin

You will be prompted to enter the password that you set earlier. After entering the password, you should see a message indicating “Login Succeeded,” confirming that you are successfully logged into the Nexus repository via Docker.

Since the repositories are newly set up, they won’t contain any images yet. To test the proxy, we will attempt to pull an image from DockerHub through our Nexus setup using the following command:

docker pull nginx-nexus.sametustaoglu.com/nginx:latest

When you run this command, Nexus should not find the image locally in your proxy repository and will instead fetch it from DockerHub. Once the image is pulled through Nexus, it will cache it, allowing any subsequent requests for this image to be served directly from Nexus, reducing the need to pull it again from DockerHub. This demonstrates the effectiveness of using Nexus as a caching proxy for Docker images. And When you check the Nexus interface, you should see the image stored in your repository.

To test the hosted repository, we will use the following commands. First, we’ll pull the busybox image to our local machine. Then, we’ll tag it with our Nexus repository’s address and push it to the hosted repository. Here are the steps:

docker pull busybox
docker tag busybox:latest nginx-nexus.sametustaoglu.com/hosted/busybox:latest
docker push nginx-nexus.sametustaoglu.com/hosted/busybox:latest
hosted-repository

Now that we’ve completed the setup with Nginx, we’ll proceed to set up another Nexus instance using Traefik on a different VM that already has Docker installed. We’ll configure this new Nexus to use the images from the hosted repository set up with Nginx through proxying. Let’s begin by generating a certificate for this new Nexus instance and storing the certificate files in a certs folder within the home directory. Before obtaining the SSL certificate with Certbot, it’s crucial to remember to set up the DNS records for your domain names at your hosting provider. Here are the commands to do this:

sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl status nginx

sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

sudo certbot certonly --nginx -d traefik-nexus.sametustaoglu.com
sudo systemctl stop nginx
mkdir certs
sudo cp /etc/letsencrypt/live/traefik-nexus.sametustaoglu.com/fullchain.pem certs/
sudo cp /etc/letsencrypt/live/traefik-nexus.sametustaoglu.com/privkey.pem certs/
sudo chown -R ubuntu:ubuntu certs/

Let’s prepare the docker-compose.yaml file for the Nexus setup that will use Traefik. In this configuration, Traefik will have two volumes: one for the SSL certificates and another to access the local Docker daemon files for routing. We will use labels in the Nexus service configuration to direct Traefik on how to route requests. There will be two main routes: the / path for the Nexus homepage and the /hosted path to proxy the repository we set up with Nginx.

version: "3.3"
services:
traefik:
image: "traefik:v2.8"
restart: unless-stopped
command:
- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.file.directory=/certs/"
- "--entrypoints.web.address=:80"
- "--entryPoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--serverstransport.insecureskipverify=true"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./certs/:/certs/"
nexus:
image: sonatype/nexus3:3.59.0
restart: unless-stopped
volumes:
- './nexus-data:/nexus-data'
labels:
- "traefik.enable=true"
- "traefik.http.routers.nexus.rule=Host(`traefik-nexus.sametustaoglu.com`) && PathPrefix(`/`)"
- "traefik.http.services.nexus.loadbalancer.server.port=8081"
- "traefik.http.routers.nexus.service=nexus"
- "traefik.http.routers.nexus.entrypoints=websecure"
- "traefik.http.routers.nexus.tls=true"
- "traefik.http.routers.proxy.rule=Host(`traefik-nexus.sametustaoglu.com`) && PathPrefix(`/v2/hosted`)"
- "traefik.http.services.proxy.loadbalancer.server.port=8082"
- "traefik.http.routers.proxy.service=proxy"
- "traefik.http.routers.proxy.entrypoints=websecure"
- "traefik.http.routers.proxy.tls=true"
- "traefik.http.routers.dockerhub.rule=Host(`traefik-nexus.sametustaoglu.com`) && PathPrefix(`/v2`)"
- "traefik.http.services.dockerhub.loadbalancer.server.port=8083"
- "traefik.http.routers.dockerhub.service=dockerhub"
- "traefik.http.routers.dockerhub.entrypoints=websecure"
- "traefik.http.routers.dockerhub.tls=true"

To specify the location of the SSL certificates in Traefik, we will create a certificates.yaml file within the certs folder. This file will contain configuration details for using the SSL certificates with Traefik. Here is what the content of the certificates.yaml file might look like:

tls:
certificates:
- certFile: /letsencrypt/fullchain.pem
keyFile: /letsencrypt/privkey.pem

Use the command docker-compose up to start the services, and then change the permissions of the created nexus-data folder with the command sudo chmod 777 nexus-data/ to ensure the proper permissions are set for access and modification.

Access the interface at https://traefik-nexus.sametustaoglu.com and create a Docker repository of the proxy type. Use port 8082 and set the proxy to https://nginx-nexus.sametustaoglu.com.

To log in to the new Nexus instance, use the following command:

docker login traefik-nexus.sametustaoglu.com -u admin

Since the new Nexus instance doesn’t contain any container images, and we’ve set up a proxy to the Nexus instance managed by Nginx, let’s pull the busybox image from the first Nexus using the following command:

docker pull traefik-nexus.sametustaoglu.com/hosted/busybox:latest

To summarize, we set up Nexus on two different VMs using Nginx as a reverse proxy on one and Traefik on the other. In the Nexus managed by Nginx, we created two Docker repositories: a proxy type for DockerHub at the / path and a hosted type at the /hosted path. In the Nexus managed by Traefik, we also established two Docker repositories, both of proxy type: one for DockerHub at the / path and another at the /hosted path, which proxies to the Nexus set up with Nginx.

I hope this article has been useful.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top