Контейнер для док-станции nginx: 502 плохой ответ шлюза

У меня есть сервис, слушая порт 8080. Это не контейнер.

Затем я создал контейнер nginx, используя официальное изображение:

docker run --name nginx -d -v /root/nginx/conf:/etc/nginx/conf.d -p 443:443 -p 80:80 nginx

В конце концов:

# netstat -tupln | grep 443
tcp6       0      0 :::443                  :::*                    LISTEN      3482/docker-proxy
# netstat -tupln | grep 80
tcp6       0      0 :::80                   :::*                    LISTEN      3489/docker-proxy
tcp6       0      0 :::8080                 :::*                    LISTEN      1009/java

Конфигурация Nginx:

upstream eighty {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name eighty.domain.com;

    location / {
      proxy_pass                        http://eighty;
    }
}

Я проверил, что я могу подключиться к этому серверу с помощью # curl http://127.0.0.1:8080

 <html><head><meta http-equiv='refresh'
 content='1;url=/login?from=%2F'/><script>window.location.replace('/login?from=%2F');</script></head><body
 style='background-color:white; color:white;'>
 ...

Кажется, что работает хорошо, однако, когда я пытаюсь получить доступ к моему браузеру, nginx сообщает bt ответ на плохой шлюз 502.

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

ИЗМЕНИТЬ

Журналы, где upstream { server 127.0.0.1:8080; }:

2016/07/13 09:06:53 [error] 5#5: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 62.57.217.25, server: eighty.domain.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "eighty.domain.com"
62.57.217.25 - - [13/Jul/2016:09:06:53 +0000] "GET / HTTP/1.1" 502 173 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0" "-"

Журналы, где upstream { server 0.0.0.0:8080; }:

62.57.217.25 - - [13/Jul/2016:09:00:30 +0000] "GET / HTTP/1.1" 502 173 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0" "-" 2016/07/13 09:00:30 [error] 5#5: *1 connect() failed (111: Connection refused) while connecting to upstream, client:
62.57.217.25, server: eighty.domain.com, request: "GET / HTTP/1.1", upstream: "http://0.0.0.0:8080/", host: "eighty.domain.com" 2016/07/13 09:00:32 [error] 5#5: *3 connect() failed (111: Connection refused) while connecting to upstream, client: 62.57.217.25, server: eighty.domain.com, request: "GET / HTTP/1.1", upstream: "http://0.0.0.0:8080/", host: "eighty.domain.com"
62.57.217.25 - - [13/Jul/2016:09:00:32 +0000] "GET / HTTP/1.1" 502 173 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0" "-"

Любые идеи?

Ответ 1

Эта проблема

Localhost немного сложнее, когда дело доходит до контейнеров. Внутри док-контейнера localhost указывает на сам контейнер. Это означает, что с восходящим потоком, как это:

upstream foo{
  server 127.0.0.1:8080;
}

или же

upstream foo{
  server 0.0.0.0:8080;
}

вы говорите nginx передать ваш запрос локальному хосту. Но в контексте docker-контейнера localhost (и соответствующие IP-адреса) указывают на сам контейнер:

enter image description here

Обращаясь к 127.0.0.1, вы никогда не достигнете своего хост-компьютера, если ваш контейнер не находится в сети хоста.

Решения

Хост сеть

Вы можете запустить nginx в той же сети, что и ваш хост:

docker run --name nginx -d -v /root/nginx/conf:/etc/nginx/conf.d --net=host nginx

Обратите внимание, что вам не нужно выставлять какие-либо порты в этом случае.

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

Доступ к удаленному IP-адресу хостов

Другим подходом является перенастройка вашей исходной директивы nginx для прямого подключения к вашему хост-компьютеру путем добавления его удаленного IP-адреса:

upstream foo{
  //insert your hosts ip here
  server 192.168.99.100:8080;
}

Теперь контейнер пройдет через сетевой стек и правильно определит ваш хост:

enter image description here

Вы также можете использовать свое DNS-имя, если оно у вас есть. Убедитесь, что докер знает о вашем DNS-сервере.

Ответ 2

Мне помогла эта строка кода proxy_set_header Host $http_host;

server {
   listen            80;
   server_name  localhost;
location / {
   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 Host $http_host;
   proxy_set_header X-NginX-Proxy true;

   proxy_redirect off;
   proxy_pass http://myserver;
}

Ответ 3

nginx.sh

ip=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -n 1)

docker run --name nginx --add-host="host:${ip}" -p 80:80 -d nginx

nginx.conf

location / {
    ...
    proxy_pass http://host:8080/;
}

Это работает для меня

Ответ 4

Что вы можете сделать, это настроить proxy_pass чтобы с точки зрения container адрес указывал на ваш реальный хост.

Чтобы получить адрес host с точки зрения контейнера, вы можете сделать следующее в Windows с докером 18.03 (или более поздней):

Запустите bash для контейнера с хоста, где имя образа - nginx (работает в Alpine Linux distribution):

 docker run -it nginx /bin/ash

Затем запустите внутри контейнера

/ # nslookup host.docker.internal

Name:      host.docker.internal
Address 1: 192.168.65.2

192.168.65.2 - это IP-адрес хоста, а не IP-адрес моста, как в ответе spinus.

Я использую здесь host.docker.internal:

Хост имеет изменяющийся IP-адрес (или не имеет, если у вас нет доступа к сети). Начиная с 18.03, мы рекомендуем подключаться к специальному DNS-имени host.docker.internal, который разрешает внутренний IP-адрес, используемый хостом. Это для целей разработки и не будет работать в производственной среде за пределами Docker для Windows.

Затем вы можете изменить конфигурацию nginx на: proxy_pass http://192.168.65.2:{your_app_port};: proxy_pass http://192.168.65.2:{your_app_port};

и это должно работать нормально.

Не забудьте указать тот же port с которым работает ваше локальное приложение.

Ответ 5

У меня была эта проблема, и оказалось, что проблема с контейнером Docker не запускается из-за проблемы с разрешениями.

В моем случае работает

docker-compose ps 

показал, что контейнер не был запущен и вышел со статусом 1. Оказывается, что при переносе на новую машину были потеряны разрешения. Настройка разрешений для известного сотрудника пользователя в родительском каталоге устранила проблему для меня, и я смог запустить службу Docker, где, как и раньше, я получал

nginx_1_c18a7f6f7d6d | chown: /var/www/html: Operation not permitted