Adam
Adam

Reputation: 5455

docker nginx reverse proxy no errors but get empty payload returned

I'm having no luck putting a bare bones nginx reverse proxy in front of my java/tomcat app, which works fine on port 8080 . My browser gets back an empty response, and I see no logging or errors on the servers.

This is my nginx Dockerfile:

FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 10040
CMD ["nginx"]

and my nginx.conf from nginx -T

$ docker run -p 10040:8080 --name rproxy --rm we1p2xxxxxxx.xxx.xx.com:11095/myapp-rproxy nginx -T
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# configuration file /etc/nginx/nginx.conf:
daemon off;
error_log /dev/stdout info;
worker_processes 1;

events { worker_connections 1024; }

http {
    access_log /dev/stdout;
    sendfile on;

    upstream docker-myapp {
        server localhost:8080;
    }

    server {
        listen 10040;

        location / {
            proxy_pass         http://docker-myapp;
            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;
        }
    }

}

When I call http://localhost:10040/ from a browser, I get nothing back - an empty response. Not even a response status.

Nothing is logged either - no error, no access log, both of which I have redirected to /dev/stdout

This is the start-up logging output from nginx:

$ docker run -p 10040:8080 --name rproxy --rm we1pxxxxxxxx.xxx.xxx.com:11095/myapp-rproxy nginx-debug
2017/11/29 14:17:06 [notice] 1#1: using the "epoll" event method
2017/11/29 14:17:06 [notice] 1#1: nginx/1.13.7
2017/11/29 14:17:06 [notice] 1#1: built by gcc 6.3.0 20170516 (Debian 6.3.0-18)
2017/11/29 14:17:06 [notice] 1#1: OS: Linux 4.9.49-moby
2017/11/29 14:17:06 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2017/11/29 14:17:06 [notice] 1#1: start worker processes
2017/11/29 14:17:06 [notice] 1#1: start worker process 7

I'm still trying to find out how to get more info from the logging - for instance, the port number it's listening on. Cygwin netstat doesn't show anything listening on the 10040 port - although I've got EXPOSE 10040 in the Dockerfile.

This is docker ps:

$ docker ps
CONTAINER ID        IMAGE                                          COMMAND                  CREATED             STATUS              PORTS                                        NAMES
03d17ec349f7        we1pxxxxxxxx.xxx.xxx.com:11095/myapp-rproxy    "nginx"                  52 seconds ago      Up 51 seconds       80/tcp, 10040/tcp, 0.0.0.0:10040->8080/tcp   rproxy
eaf3ed033908        we1pxxxxxxxx.xxx.xxx.com:11095/myapp           "/bin/sh -c 'java ..."   2 hours ago         Up 2 hours          0.0.0.0:8080->8080/tcp                       myapp

This is what happens when I use curl:

$ curl -i http://localhost:8080
HTTP/1.1 401
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
WWW-Authenticate: Negotiate
WWW-Authenticate: Basic realm="xx.xx.xx.COM"
Content-Length: 0
Date: Wed, 29 Nov 2017 15:57:38 GMT

$ curl -i http://localhost:10040
curl: (52) Empty reply from server
$

I'm using docker 17.09.0-ce-win33 on Windows 10, with cygwin.

Any hope, world?

[UPDATE 2017-11-30] Ports gotcha

Simple mistake pointed out by Alexander Altshuler in his answer - I was attaching nginx to 10040 inside the docker container already, so by trying to map 10040 to 80 with the command line -p 10040:80 parameter was blocking my requests - from which a couple of questions arise:

$ docker ps
CONTAINER ID        IMAGE                                          COMMAND                  CREATED             STATUS              PORTS                              NAMES
b6379d40d0c2        we1pxxxxxxxx.xxx.xxx.com:11095/myapp           "/bin/sh -c 'java ..."   2 minutes ago       Up 2 minutes        0.0.0.0:8080->8080/tcp             myapp
d3d5feb9e63f        we1pxxxxxxxx.xxx.xxx.com:11095/myapp-rproxy    "nginx"                  20 minutes ago      Up 20 minutes       80/tcp, 0.0.0.0:10040->10040/tcp   rproxy

and doing curl I get this:

$ curl http://localhost:10040

<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.13.7</center>
</body>
</html>

and NGINX spits out:

2017/11/30 10:07:32 [error] 5#5: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.17.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "localhost:10040"
2017/11/30 10:07:32 [warn] 5#5: *1 upstream server temporarily disabled while connecting to upstream, client: 172.17.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "localhost:10040"
2017/11/30 10:07:32 [error] 5#5: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.17.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "localhost:10040"
2017/11/30 10:07:32 [warn] 5#5: *1 upstream server temporarily disabled while connecting to upstream, client: 172.17.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "localhost:10040"
172.17.0.1 - - [30/Nov/2017:10:07:32 +0000] "GET / HTTP/1.1" 502 173 "-" "curl/7.56.1"
2017/11/30 10:07:32 [info] 5#5: *1 client 172.17.0.1 closed keepalive connection

Obviously there is still something rotten in the state of Denmark, but now I'm getting some logging I'm confident I'll sort this one out.

Upvotes: 0

Views: 7758

Answers (2)

Adam
Adam

Reputation: 5455

Posted the solution first here:

Using a user-defined bridge network:

docker network create -d bridge myapp-net

And then I launch the containers, attaching them to the myapp-net:

docker run -p 8080:8080 --network=myapp-net --name myapp --rm myregistry:11095/myapp

docker run -p 10040:443 --network=myapp-net --name rproxy --rm myregistry:11095/myapp-rproxy

Caveat: I don't yet understand why the default docker bridge network won't work despite reading the docker docs

Upvotes: 0

Alexander Altshuler
Alexander Altshuler

Reputation: 3064

The command to run docker coniatner should start with

docker run -p 10040:10040 ...

Update:

why is the docker ps PORTS field showing 80/tcp? Surely that's not open (curl connection times out)

I can imagine only one reason - you did provide docker run -p 80 ...

Why nginx responds with 502 Bad Gateway is clear:

you configured nginx to connect to localhost:8080, but from within container your backend run on external host.

The usual practice here - create user defined network:

docker network create --driver bridge mynetwork
docker run --network=isolated_nw -p 10040:8080 --name rproxy ...
docker run --network=isolated_nw --name myapp ...

Nginx config should looks like below:

daemon off;
error_log /dev/stdout info;
worker_processes 1;

events { worker_connections 1024; }

http {
    # use docker embedded DNS server to resolve myapp host name
    resolver 127.0.0.11;

    access_log /dev/stdout;
    sendfile on;

    upstream docker-myapp {
        server myapp:8080; # !!!
    }

    server {
        listen 10040;

        location / {
            proxy_pass         http://docker-myapp;
            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;
        }
    }

}

Upvotes: 1

Related Questions