Nginx в качестве обратного прокси-сервера для Nexus - не удается подключиться в среде докеров

У меня есть среда, построенная на контейнерах докеров (в boot2docker). У меня есть следующий файл docker-compose.yml для быстрой настройки серверов nginx и nexus:

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 имеет следующую конфигурацию (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";
        }
    }
}

Нексус вроде работает очень хорошо. Я успешно звоню curl http://localhost:8081 на хост-машину docker. Это вернет мне html сайта входа в систему nexus. Теперь хочу попробовать сервер nginx. Он настроен на прослушивание порта 443, но SSL сейчас отключен (я хотел протестировать его перед тем, как погрузиться в конфигурацию SSL). Как вы могли заметить, мой контейнер ngix сопоставляет порт 443 с портом 5043. Таким образом, я пытаюсь использовать следующую команду curl: curl -v http://localhost:5043/. Теперь я ожидаю, что мой http-запрос будет отправлен на nginx и проксирован на proxy_pass http://nexus:8081/; nexus. Имя хоста Nexus отображается в сети контейнеров докеров и доступно из контейнера nginx. К сожалению, в ответ я получаю:

*   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

Я проверял журналы nginx, ошибки, доступ, но эти журналы пусты. Может кто-нибудь помочь мне решить эту проблему? Это должен быть простой пример проксирования запросов, но, может быть, я неправильно понимаю какую-то концепцию?


person Artur Skrzydło    schedule 24.10.2017    source источник
comment
логи должны где-то храниться ... Попробуйте docker-compose logs и покажите мне вывод, пожалуйста.   -  person Bukharov Sergey    schedule 24.10.2017
comment
Примонтированный каталог работает нормально. Я предполагаю, что установка этого контейнера не работает. проверьте журналы контейнера nginx с помощью $ docker logs CONTAINER_ID   -  person Jinna Balu    schedule 24.10.2017
comment
ничего, логи пусты, кажется, что ничего не попадает на прокси-сервер   -  person Artur Skrzydło    schedule 24.10.2017
comment
Можете ли вы попробовать запустить nginx без тома   -  person Jinna Balu    schedule 24.10.2017
comment
Почему ? благодаря тому у меня есть файл nginx.conf. Без этого мой тест был бы бессмысленным.   -  person Artur Skrzydło    schedule 24.10.2017


Ответы (3)


Есть ли в вашем nginx conf директива upstream (помещенная в директиву http)?

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

Только тогда nginx сможет правильно решить эту проблему. docker-compose имя службы nexus не внедряется в nginx контейнер во время выполнения.

Вы можете попробовать links в docker-compose:

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

Это дает вам alias для связанного контейнера в вашем /etc/hosts. Но вам все равно нужно upstream directive. Обновление: если это возможно, вы также можете использовать имена непосредственно в nginx directives, например location.

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

person arne    schedule 24.10.2017
comment
на самом деле директива upstream не является обязательной. В моем случае причиной ошибки была listen 443 ssl. Без ssl все работает корректно - person Artur Skrzydło; 03.12.2017
comment
@ ArturSkrzydło true (upstream directive не обязательно, если имена уже разрешимы) ... Я исправил ответ. - person arne; 04.12.2017

В качестве ответа @arnold вам не хватает конфигурации восходящего потока в вашем nginx. Я видел, что вы используете образ nexus stefanprodan, см. его блог для полной комплектации. Ниже вы можете найти мой (не забудьте открыть порты 8081 и 5000 нексуса, даже если точка входа - 443). Кроме того, вам необходимо включить сертификат, потому что клиент докера требует работы ssl:

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

Сертификаты генерируются с помощью letsencrypt или certbot. Остальная часть конфигурации должна иметь отметку A + в анализе ssllabs, как это объясняется здесь

person Carlos Cavero    schedule 02.12.2017

Ваш docker-compose из порта 5000 является динамическим (потому что он не был открыт), поэтому вы не можете подключить порт 5000, потому что

ports:
      - 8081:8081
      - 5000:5000

неэффективны.

вы можете использовать так:

  1. Создайте новый Dockerfile и откройте порт 5000 (имя у меня)

    FROM sonatype/nexus3:3.16.2
    EXPOSE 5000```
    
    
  2. Используйте новый образ, чтобы запустить контейнер и опубликовать порт.

version: "3.7"
    services:
      nexus:
        image: 'feibor/nexus:3.16.2-1'
        deploy:
          placement:
            constraints:
              - node.hostname == node1
          restart_policy:
            condition: on-failure
        ports:
          - 8081:8081/tcp
          - 5000:5000/tcp
        volumes:
          - /mnt/home/opt/nexus/nexus-data:/nexus-data:z

person Lee Andrew    schedule 08.06.2019