88

I've a service listening to 8080 port. This one is not a container.

Then, I've created a nginx container using official image:

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

After all:

# 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 configuration is:

upstream eighty {
    server 127.0.0.1:8080;
}

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

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

I've checked I'm able to connect with with this server with # 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;'>
 ...

It seems running well, however, when I'm trying to access using my browser, nginx tells bt a 502 bad gateway response.

I'm figuring out it can be a problem related with the visibility between a open by a non-containerized process and a container. Can I container stablish connection to a port open by other non-container process?

EDIT

Logs where 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" "-"

Logs where 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" "-"

Any ideas?

Fopa Léon Constantin
  • 11,863
  • 8
  • 48
  • 82
Jordi
  • 20,868
  • 39
  • 149
  • 333
  • Just a quick guess, could it be due to the server address? Can you try and change it from 127.0.0.1 to 0.0.0.0? If it's not the case then some other applicative failure occurs, check the logs or post them and I'll try to see what's the matter, also add the port (8080) to `http://eighty` at the `proxy_pass` line. – Yaron Jul 13 '16 at 08:52
  • I've just added logs on post right now. – Jordi Jul 13 '16 at 09:07
  • Have you tried changing the `proxy_pass` as well? – Yaron Jul 13 '16 at 09:09
  • Yes, I've set `proxy_pass` to `http://0.0.0.0:8080`. The same problem... – Jordi Jul 13 '16 at 09:11
  • I see, the logs show you are using IPv6, can you try and change it to IPv4? – Yaron Jul 13 '16 at 09:16
  • By default it set up using IPv6. I've absolutly no idea how to change it. What do I need to change? docker behaviour or OS behaviour? However, I've performed a `curl http:127.0.0.1:8080` and it responds me well... – Jordi Jul 13 '16 at 09:19
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/117182/discussion-between-yaron-and-jordi). – Yaron Jul 13 '16 at 09:22
  • For me the fix was to add a trailing slash to the proxy_pass directive, as per http://stackoverflow.com/a/31357655 – user326608 Sep 10 '16 at 08:12
  • 1
    were you using docker on linux or windows? – Adam Nov 30 '17 at 13:26
  • probably you missed the `/` after your proxy_pass address! – funder7 Dec 09 '20 at 01:01

8 Answers8

158

The Problem

Localhost is a bit tricky when it comes to containers. Within a docker container, localhost points to the container itself. This means, with an upstream like this:

upstream foo{
  server 127.0.0.1:8080;
}

or

upstream foo{
  server 0.0.0.0:8080;
}

you are telling nginx to pass your request to the local host. But in the context of a docker-container, localhost (and the corresponding ip addresses) are pointing to the container itself:

enter image description here

by addressing 127.0.0.1 you will never reach your host machine, if your container is not on the host network.

Solutions

Host Networking

You can choose to run nginx on the same network as your host:

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

Note that you do not need to expose any ports in this case.

This works though you lose the benefit of docker networking. If you have multiple containers that should communicate through the docker network, this approach can be a problem. If you just want to deploy nginx with docker and do not want to use any advanced docker network features, this approach is fine.

Access the hosts remote IP Address

Another approach is to reconfigure your nginx upstream directive to directly connect to your host machine by adding its remote IP address:

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

The container will now go through the network stack and resolve your host correctly:

enter image description here

You can also use your DNS name if you have one. Make sure docker knows about your DNS server.

ShrimpPhaser
  • 3,257
  • 1
  • 23
  • 22
  • 7
    Excellent & straight answer. Saved me a lot of time – Manoochehr Dadashi May 14 '18 at 21:30
  • 1
    How would I connect nginx to a docker container if both are running on kubernetes? As far as I understand it, there is no fixed IP, I could point nginx at as there could be multiple instances of the container running at the same time. – finngu Sep 29 '19 at 16:53
  • Found an answer to my kubernetes question here: https://stackoverflow.com/questions/50103242/nginx-config-for-django-app-in-kubernetes-cluster – finngu Sep 29 '19 at 17:32
  • 1
    My request to 192.168.*.* keeps timing out – Johnny Metz Dec 11 '19 at 07:27
  • 1
    for docker-compose you can use network_mode: "host" – Aleem Jan 15 '21 at 16:51
  • @Aleem do you could share example using network_mode in gist template docke-compose? https://gist.github.com/jonathasborges1/592b79245c2b8c686f1cb4b79cf4aff0 – jonathasborges1 Jul 30 '22 at 15:54
11

For me helped this line of code 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;
}
  • 1
    I spent days trying to figure how why networking is so slow between my nginx container&django container on docker-compose bridge network. This has really been a lifesaver for me. Thanks. – Bossam Aug 21 '19 at 01:05
  • 1
    I cannot find any relevant documentation for `proxy_set_header X-NginX-Proxy true;` – Richard Dec 22 '21 at 16:57
11

Just to complete other answers, I'm using mac for development and using host.docker.internal directly on upstream worked for me and no need to pass the host remote IP address. Here is config of the proxy nginx:

events { worker_connections 1024; }

http {
    upstream app1 {
        server host.docker.internal:81;
    }

    upstream app1 {
        server host.docker.internal:82;
    }
    
    server {
        listen 80;
        server_name app1.com;
    
        location / {
          proxy_pass    http://app1;
        }
    }

    server {
        listen 80;
        server_name app2.com;
    
        location / {
          proxy_pass    http://app2;
        }
    }
}

As you can see, I used different ports for different apps behind the nginx proxy. I used port 81 for the app1 and port 82 for the app2 and both app1 and app2 have their own nginx containers:

For app1:

docker run --name nginx -d -p 81:80 nginx

For app2:

docker run --name nginx -d -p 82:80 nginx

Also, please refer to this link for more details: docker doc for mac

Moj
  • 358
  • 2
  • 8
5

What you can do is configure proxy_pass that from container perspective the adress will be pointing to your real host.

To get host address from container perspective you can do as following on Windows with docker 18.03 (or more recent):

Run bash on container from host where image name is nginx (works on Alpine Linux distribution):

 docker run -it nginx /bin/ash

Then run inside container

/ # nslookup host.docker.internal

Name:      host.docker.internal
Address 1: 192.168.65.2

192.168.65.2 is the host's IP - not the bridge IP like in spinus accepted answer.

I am using here host.docker.internal:

The host has a changing IP address (or none if you have no network access). From 18.03 onwards our recommendation is to connect to the special DNS name host.docker.internal, which resolves to the internal IP address used by the host. This is for development purpose and will not work in a production environment outside of Docker for Windows.

Then you can change nginx config to: proxy_pass http://192.168.65.2:{your_app_port};

and it should work fine.

Remember to provide the same port as your local application runs with.

Kamil Witkowski
  • 1,978
  • 1
  • 19
  • 33
  • @pini-cheyni (https://stackoverflow.com/users/1773972/pini-cheyni) `bin/ash` does exist - you can read about it for example here: https://unix.stackexchange.com/questions/44912/are-dash-ash-and-sh-script-100-compatible This is not typo of `bash` or `sh`. – Kamil Witkowski Dec 26 '18 at 18:10
  • you are right, on my Debian systems it doesn't exist so I thought it was a typo. – Pini Cheyni Dec 27 '18 at 07:25
1
# the upstream component nginx needs to connect to
upstream django {

    # server unix:///path/to/your/mysite/mysite.sock; # for a file socket

    server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}


location / {

        uwsgi_pass  django;
        include     /path/to/your/mysite/uwsgi_params; # the uwsgi_params file you installed
    }

complete reference: https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html

Asad-ullah Khan
  • 1,573
  • 18
  • 22
  • Please improve your question. Code + link answers are rarely suitable. Please add an additional explanation to your question as well. I have formatted the part of your answer I think was code, please check/change it to what you originally intended. I am not downvoting at this moment, but if you do not make these changes it will certainly be flagged as very low quality :( – Asad-ullah Khan Apr 13 '21 at 05:53
0

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

It‘s works for me

hehe Peng
  • 1
  • 3
0

I was getting the same error, but in my case it is because I was directing https traffic (from the load balancer - ALB) to http. Changing the protocol of the target group to http resolved it.

-1

I had this issue and it turned out to be an issue with the docker container not starting up due to a permissions issue.

In my case running

docker-compose ps 

showed that the container had not started and exited with status 1. Turns out the permissions had been lost in migrating to a new machine. Adjusting the permissions to a know staff user on the parent directory fixed the problem for me and I was then able to start docker service where as previously I was getting

nginx_1_c18a7f6f7d6d | chown: /var/www/html: Operation not permitted
Daniel
  • 505
  • 6
  • 8