Connecting to nginx on port 443 using host ip

  • Docker version 20.10.23, build 7155243
  • OS: Ubuntu Ubuntu 22.04.1 LTS or CENTOS7

Hello… I was hoping someone could explain this to me.

The following happens not only on my personal ubuntu host, but also when using a freshly installed centos7 host (using vagrant), with a fresh installation of Docker CE, (suggesting anyone should be able to re-produce this?)

Let’s say my host ip address is 192.168.1.111

If I run the following:

$ docker run --name mynginx1 -p 80:80 -d nginx

As expected, I am able to test connect to the container using nc (netcat) both via the localhost IP and the host’s actual IP:

$ nc -zv localhost 80
Connection to localhost (127.0.0.1) 80 port [tcp/http] succeeded!

$ nc -zv 192.168.1.111 80
Connection to 192.168.1.111 80 port [tcp/http] succeeded!

However if I run the following:

$ docker run --name mynginx1 -p 443:443 -d nginx

This happens:

$ nc -zv localhost 443
Connection to localhost (127.0.0.1) 443 port [tcp/https] succeeded!

$ nc -zv 192.168.1.111 443
nc: connect to 192.168.1.111 port 443 (tcp) failed: Connection refused

Why do port 80 connection attempts to my hosts’s actual IP address work fine but connection attempts to my host’s actual IP on port 443 do not? (and yet localhost on port 443 DOES work?)

Just in regards to troubleshooting, I’ve confirmed my host firewall is down. I can also 100% prove it’s NOT the host firewall as I can do this:

  1. stop docker service

  2. in one terminal session, run the command “nc -l 443” so that I have something non-docker related listening on port 443

  3. in another terminal session, I am then able to successfully perform “nc -zv 192.168.1.111 443”

This proves it is possible to connect to port 443 via my host IP address so long as I’m not using docker.

Also just to confirm, when Docker is up… I can see ports are listening as expected:

$ sudo netstat -tulpen |grep 443
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      0          5845471    517353/docker-proxy
tcp6       0      0 :::443                  :::*                    LISTEN      0          5880943    517372/docker-proxy

And here is the docker process:

$ docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED              STATUS              PORTS                                           NAMES
26035275fc27   nginx     "/docker-entrypoint.…"   About a minute ago   Up About a minute   80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   mynginx1

Finally, as mentioned above, I can re-produce this situation with a completely vanilla setup using cento7 and docker CE via vagrant. For that setup, these are my high-level steps, (and I’m suggesting anyone else would presumably get the same results as me?)

  1. boot up fresh centos7 instance using vargant

  2. install Docker CE via yum repo as per this: Install Docker Engine on CentOS | Docker Documentation

  3. ensure firewall is down:

    systemctl stop firewalld ; systemctl disable firewalld

  4. disable selinux for the current session:

    setenforce 0

  5. run nginx as per above on port 443 - get exactly the same issue

  • netcat test to port 443 on localhost works
  • netcat test to port 443 on VM’s IP (eg: 10.0.2.15) fails
  1. run nginx as per above on port 80 - everything works
  • netcat test to port 80 on localhost works
  • netcat test to port 80 on VM’s IP (eg: 10.0.2.15) works!!

Clearly I’m not understanding something… so apologies if this is a dumb question… any help would be greatly appreciated :slight_smile:

Your assumption that port 443 actually serves any content implies that you have a ngninx configuration with a server block that listens on port 443, a valid tls certificate and the configuration in your nginx.conf to use the certificate. Just to be sure: you have all this configured?

Also, you can use a container like netshoot and join into the network namespace of a container for network troubleshooting. In your case a simple netstat tln should show whether nginx actually listens on port 443:

# general usage: docker run -it --net container:<container_name> nicolaka/netshoot
docker run -it --net container:mynginx1 nicolaka/netshoot  netstat -tln

A published port (-p) does not care if inside the container actually listens on the container port…

Many thanks for the info! Really appreciate it and this does clarify a lot… however there is just one thing I am not understanding.

So you are correct… there is nothing configured and serving on port 443 within the container (also confirmed using netshoot as per you suggestion). I am just using the nginx image with no configuration and performing a simple port connection test with netcat (not curl). Based on your answer and the netshoot results, the actual container is indeed NOT listening on port 443… so makes total sense why I would NOT be able to connect to it on port 443. However the only reason I’ve mistakenly assumed I should be able to… is that I AM able to connect on port 443 when specifying “localhost” (127.0.0.1). I.E:

$ nc -zv localhost 443
Connection to localhost (127.0.0.1) 443 port [tcp/https] succeeded!

The instant I stop/destroy the nginx container… I am NO LONGER able to connect to localhost on port 443. Based on this behavior, I’ve (mistakenly) assumed it is nginx I am connecting to on port 443, and am therefore confused as to why it would not also work when connecting via the actual host IP address.

So what am I actually successfully connecting to on port 443 when using localhost after starting nginx?

For the record, I am just trying to understand what’s going on from a network perspective using basic netcat port connection tests. I realise that in the real world I would need a cert, config, etc. It’s just that the current behavior above (i.e: localhost vs real IP) is not making sense for me at the moment.

Thankyou so much again!

I am surprised netcat even indicates that it’s succeeding for localhost, because the host port is forwarded to a container port where no service is listening on. My expectation would be “Connection refused” regardless whether localhost or the host ip is used.

Note: With -p 443:443 the container port is bound to all host interfaces. With -p 172.0.0.1:443:443 it would only bind the container port to localhost.