111: Отказано в подключении прокси-сервера nginx для контейнеров Docker

  • CentOS 7

У меня есть простой контейнер Nginx proxy Docker, прослушивающий порт 80. Вот файл Dockerfile:

FROM centos:7MAINTAINER Brian Ogden# Not currently being used but may come in handyARG ENVIRONMENTRUN yum -y update && \    yum clean all && \    yum -y install http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm \    yum -y makecache && \    yum -y install nginx-1.12.0 wget# Cleanup some default NGINX configuration files we don’t needRUN rm -f /etc/nginx/conf.d/default.confCOPY /conf/proxy.conf /etc/nginx/conf.d/proxy.confCOPY /conf/nginx.conf /etc/nginx/nginx.confCMD ["nginx"]

И для этого прокси-сервера Nginx вот мой nginx.conf:

daemon off;user  nginx;worker_processes  2;error_log  /var/log/nginx/error.log warn;pid        /var/run/nginx.pid;events {    worker_connections  1024;    use epoll;    accept_mutex off;}http {    include       /etc/nginx/mime.types;    proxy_set_header X-Real-IP $remote_addr;    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;    default_type  application/octet-stream;    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;    sendfile        on;    #tcp_nopush     on;    keepalive_timeout  65;    client_max_body_size 300m;    client_body_buffer_size 300k;    large_client_header_buffers 8 64k;    gzip  on;    gzip_http_version 1.0;    gzip_comp_level 6;    gzip_min_length 0;    gzip_buffers 16 8k;    gzip_proxied any;    gzip_types text/plain text/css text/xml text/javascript application/xml application/xml+rss application/javascript application/json;    gzip_disable "MSIE [1-6]\.";    gzip_vary on;    include /etc/nginx/conf.d/*.conf;}

А вот моя конфигурация прокси-сервера:

upstream accountstaging {    server 127.0.0.1:5023;}server {    listen 80;    server_name account.staging.mysite.com;    location / {        proxy_pass         http://accountstaging;        proxy_redirect     off;        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-Host $server_name;    }}

Моя конфигурация прокси-сервера прослушивает порт 80 и пытается запрашивать запросы от account.staging.mysite.com к контейнеру Docker, работающему на том же хосте Docker, что и прокси-сервер Ngnix, прослушивающий порт 5023.

Вот мой docker-compose.yml для моего прокси-сервера Nginx:

version: '3'services:  reverseproxy:    build:       context: ./      dockerfile: docker/Dockerfile    image: tsl.devops.reverseproxy.image    container_name: tsl.devops.reverseproxy.container    ports:      - "80:80"

Вот docker-compose.yml для этого контейнера Docker, прослушивающего порт 5023:версия: '3'

services:  apistaging:    build:       context: ./      dockerfile: docker/staging/Dockerfile    image: tsl.api.example.image    container_name: tsl.api.example.container    ports:      - "127.0.0.1:5023:80"

Файл Dockerfile на самом деле не имеет большого значения для моего вопроса, но в любом случае он здесь:

FROM tsl.devops.dotnetcore.base.image:2MAINTAINER Brian OgdenWORKDIR /appCOPY ./src/Tsl.Example/bin/Release/netcoreapp2.0/publish .ENTRYPOINT ["dotnet", "Tsl.Example.dll"]

Я последовал за ним этот пример чтобы настроить мой прокси-сервер.

Ранее я задавал соответствующий вопрос на форумах Stackexchange здесь и здесь. Этот вопрос я усовершенствовал и упростил сценарий до простой переадресации запроса прокси-сервером одному контейнеру Docker, прослушивающему порт 5023.

Поскольку мой базовый образ - CentOS, я следовал это здесь чтобы убедиться, что SELinux разрешает пересылку на порт 5023

Благодаря этому вопрос и ответ здесь, я смог понять, что у меня возникли две проблемы:

  1. контейнеры имеют разные сети Docker по умолчанию, поскольку я использую два разных файла docker-compose.yml, я предполагал, что мой прокси-сервер Ngnix будет работать полностью независимо от любого из моих контейнеров API, включая docker-compose, подробнее об этом ниже
  2. вторая проблема заключается просто в том, что я попытался подключиться к прокси-серверу 127.0.0.1:5023, который является localhost внутри контейнера Ngnix, а не к сети за пределами прокси-контейнера Nginx

Таким образом, разные сети по умолчанию, создаваемые docker-compose для моего контейнера Nginx proxy docker и моего контейнера api docker, связаны с тем, что у меня есть два разных файла docker-compose.yml. Это связано с тем, что у меня есть сборки Jenkins для многих микросервисов API, поэтому у них есть независимые файлы docker-compose, и мне нужен был прокси-сервер Nginx для пересылки запросов на порт 80 каждому микросервису.

Чтобы проверить это, создал docker-compose.yml для обоих контейнеров, API и прокси-сервера Nginx:

version: '3'services:  reverseproxy:    build:       context: ./      dockerfile: docker/nginxproxy/docker/Dockerfile    image: tsl.devops.reverseproxy.image    container_name: tsl.devops.reverseproxy.container    ports:      - "80:80"  apistaging:    build:       context: ./      dockerfile: docker/staging/Dockerfile    image: tsl.api.example.image    container_name: tsl.api.example.container    ports:      - "5023:5023"    environment:       ASPNETCORE_URLS: http://+:5023

Да, все еще была проблема, прокси-сервер переходит на http //: 127.0.0.1: 5023, эта пересылка остается в контейнере Nginx Docker и никогда не находит API, запущенный на хосте Docker, мне просто нужно было использовать имя службы docker-compose.yml, чтобы добраться до него:

upstream accountstaging {    server apistaging:5023;}server {    listen 80;    server_name account.staging.mysite.com;    location / {        proxy_pass         http://accountstaging;        proxy_redirect     off;        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-Host $server_name;    }}

У меня была эта проблема, но моя проблема заключалась в том, что у меня было две папки, в обеих из которых были файлы docker-compose.yml, в обеих из которых была служба с именем "web". Я изменил название одной из служб.

Полная картина, чтобы помочь кому-то, кто борется с сетями docker так сильно, как я был (есть?):

Проекты Docker-compose часто используют nginx в качестве обратного прокси-сервера для маршрутизации http-трафика к другим службам docker. nginx был сервисом в моем projectfolder/docker-compose.yml который был подключен к двум сетям docker.

Одной из них была сеть по умолчанию, созданная, когда я использовал docker-compose up на projectfolder/docker-compose.yml (Он назван projectfolder_default и службы подключаются к нему по умолчанию, ЕСЛИ у вас нет networks свойство для вашей службы в другой сети, затем убедитесь, что вы добавили - default к списку). Когда я бежал docker network ls Я видел projectfolder_default в списке, и когда я побежал docker network inspect projectfolder_default Я видел контейнер nginx, так что все было хорошо.

Другой была сеть под названием my_custom_network это я устроил сам. У меня был сценарий запуска, который создавал его, если он не существовал, используя https://stackoverflow.com/a/53052379/13815107 Мне это было нужно для того, чтобы поговорить с web служба в otherproject/docker-compose.yml. Я правильно добавил my_custom_network к:

  • nginx список сетей сервиса projectfolder/docker-compose.yml
  • дно projectfolder/docker-compose.yml
  • web сети сервиса в otherproject/docker-compose.yml
  • дно otherproject/docker-compose.yml

Сеть обнаружилась и имела правильные контейнеры, использующие docker network ls и docker network inspect my_custom_network

Однако я предположил, что вызов http://web будет сопоставляться со службой docker web.projectfolder_default. Я ошибся. Я открыл оболочку в контейнере nginx (docker exec -it nginx sh). Когда я использовал ping web (возможно, потребуется apt-get update, apt-get install iputils-ping) это удалось, но он напечатал URL-адрес с my_custom_network вот так я и понял, в чем ошибка.

папка проекта/docker-compose.yml

  services:    # http://web did NOT map to this service!! Use http://web.main_default or change the names    web:      ...     nginx:        ...      links:        - web      networks:        - default        - my_custom_network    ...  networks:    - my_custom_network      external: true

otherproject/docker-compose.yml

  services:    # http://web connected to this service instead. You could use http://web.my_custom_network to call it out instead    web:      ...       networks:        - default        - my_custom_network    ...  networks:    - my_custom_network      external: true

папка проекта/.../nginx/server.conf.template (рядом с файлом Dockerfile)...

server {    ...    location /auth {        internal;        # This routed to wrong 'web'        proxy_pass              http://web:9001;        proxy_pass_request_body off;        proxy_set_header        Content-Length "";    }    location / {        alias /data/dist/;    }    location /robots.txt {        alias /robots.txt;    }    # Project Folder backend    location ~ ^/(api|login|logout)/ {        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_connect_timeout 300s;        proxy_read_timeout 300s;        # This routed to wrong 'web'        proxy_pass http://web:9001;    }    # Other project UI    location /other-project {        alias /data/other-project-client/dist/;    }    # Other project Django server    location ~ ^/other-project/(rest)/ {        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_connect_timeout 300s;        proxy_read_timeout 300s;        # This should work        proxy_pass http://web.my_custom_network:8000;    }}