Nginx as reverse proxy server for Nexus - can'

2019-05-11 13:41发布

问题:

I have environment builded upon docker containers (in boot2docker). I have following docker-compose.yml file to quickly setup nginx and nexus servers :

version: '3.2'

services:
  nexus:
    image: stefanprodan/nexus
    container_name: nexus
    ports:
      - 8081:8081
      - 5000:5000

  nginx:
    image: nginx:latest
    container_name: nginx
    ports:
      - 5043:443
    volumes:
      - /opt/dm/nginx2/nginx.conf:/etc/nginx/nginx.conf:ro

Nginx has following configuration (nginx.conf)

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    proxy_send_timeout 120;
    proxy_read_timeout 300;
    proxy_buffering    off;
    keepalive_timeout  5 5;
    tcp_nodelay        on;

    server {
        listen         80;
        server_name    demo.com;

    return         301 https://$server_name$request_uri;
    }

    server {
        listen   443 ssl;
        server_name  demo.com;

        # allow large uploads of files - refer to nginx documentation
        client_max_body_size 1024m;

        # optimize downloading files larger than 1G - refer to nginx doc before adjusting
        #proxy_max_temp_file_size 2048m

        #ssl on;
        #ssl_certificate      /etc/nginx/ssl.crt;
        #ssl_certificate_key  /etc/nginx/ssl.key;

        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 "https";
        }
    }
}

Nexus seems to work very well. I call sucessfully curl http://localhost:8081 on docker host machine. This return me html of nexus login site. Now I want to try nginx server. It is configured to listen on 443 port, but SSL is right now disabled (I wanted to test it before diving into SSL configuration). As you can notice, my ngix container maps port 443 to port 5043. Thus, I try to use following curl command : curl -v http://localhost:5043/. Now I expect that my http request is going to be send to nginx and proxied to proxy_pass http://nexus:8081/; nexus. Nexus hostname is visible within docker container network and is accesible from nginx container. Unfortunately in reponse I receive :

*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 5043 (#0)
> GET / HTTP/1.1
> Host: localhost:5043
> User-Agent: curl/7.49.1
> Accept: */*
>
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server

I was checking nginx logs, error, access but these logs are empty. Can somebody help me solving this problem ? It should be just a simple example of proxying requests, but maybe I misunderstand some concept ?

回答1:

As @arnold's answer you are missing the upstream configuration in your nginx. I saw you are using the stefanprodan nexus image, see his blog for the full configuration. Below you can find mine (remember to open ports 8081 and 5000 of nexus even the entrance point is the 443). Besides you need to include the certificate because docker client requires ssl working:

worker_processes 2;

events {
    worker_connections 1024;
}

http {
    error_log /var/log/nginx/error.log warn;
    access_log  /dev/null;
    proxy_intercept_errors off;
    proxy_send_timeout 120;
    proxy_read_timeout 300;

    upstream nexus {
        server nexus:8081;
    }

    upstream registry {
        server nexus:5000;
    }

    server {
        listen 80;
        listen 443 ssl default_server;
        server_name <yourdomain>;

        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

        ssl_certificate /etc/letsencrypt/live/<yourdomain>/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/<yourdomain>/privkey.pem;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_dhparam /etc/ssl/certs/dhparam.pem;
        ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";

        keepalive_timeout  5 5;
        proxy_buffering    off;

        # allow large uploads
        client_max_body_size 1G;

        location / {
            # redirect to docker registry
            if ($http_user_agent ~ docker ) {
                    proxy_pass http://registry;
            }
            proxy_pass http://nexus;
            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 "https";
        }
    }
}

The certificates are generated using letsencrypt or certbot. The rest of the configuration is to have an A+ in ssllabs analysis as it is explained here



回答2:

Do you have an upstream directive in your nginx conf (placed within the http directive)?

upstream nexus {
    server <Nexus_IP>:<Nexus_Port>;
}

Only then nginx can correctly resolve it. The docker-compose service name nexus is not injected to the nginx container on runtime.

You can try links in docker-compose:

https://docs.docker.com/compose/compose-file/#links

This gives you an alias for the linked container in your /etc/hosts. But you still need an upstream directive. Update: If resolvable, you can as well use the names directly in nginx directives like location.

https://serverfault.com/questions/577370/how-can-i-use-environment-variables-in-nginx-conf