Score:0

Why does curl inside Docker to a subdomain in the same Host use private IP address?

us flag

Consider I have docker-subdomain.mydomain.com pointing to a website in a Docker container, and host-subdomain.mydomain.com pointing to a website in the Host itself. Both these websites are in the same Host and IP address.

When the PHP code of the docker-subdomain.mydomain.com inside Docker makes a curl call to host-subdomain.mydomain.com, and that host-subdomain.mydomain.com logs the IP address of the caller, it appears to be an IP address starting with "172.", which means it's the private IP address of the docker container.

I'm wondering how is the private IP address used, if the DNS of host-subdomain.mydomain.com is the public IP, so I'd think it would use the external interface to connect? (like it happens when a PHP script executes curl in the host itself, outside Docker)

How does Docker know that host-subdomain.mydomain.com points to the same host?

--

Note: I'm not asking how to bypass/change this behavior - I'm just curious, as it's doing exactly what I wanted it to do, but I don't understand why.

Score:0
pt flag

I'm wondering how is the private IP address used, if the DNS of host-subdomain.mydomain.com is the public IP, so I'd think it would use the external interface to connect?

You're looking at the ip address of the client, not the ip address to which curl is connecting. The process looks something like:

  1. Your PHP code calls something like curl host-subdomain.mydomain.com

  2. curl looks up the name host-subdomain.mydomain.com

  3. curl find the address (e.g.) 100.64.0.100

  4. curl opens a connection to 100.64.0.100

  5. The kernel looks for a route to that address

  6. Inside the container, the routing table looks something like:

    default via 172.17.0.1 dev eth0
    172.17.0.0/16 dev eth0 scope link  src 172.17.0.2
    
  7. Because the container doesn't have a direct route to 100.64.0.100, it uses the default route, which corresponds to the docker bridge on your host.

  8. Your application on the host sees a connection originating from the docker bridge with the ip address of the container.

In all of these steps, the connection is from the container ip address to the resolved address of host-subdomain.mydomain.com.


You have this:

enter image description here

Your container (172.20.0.2) has route to the host address ("100.64.0.100" in this example) via its default route (172.20.0.1). Your host has a route to the container (via the br-1234 interface).

Nuno avatar
us flag
Thank you. However, regarding your step 2 and 3 -- why would the lookup return a private IP, if the DNS has a public IP? (the IP of the host)
pt flag
I think you have misunderstood the answer -- the lookup does **not** return a private ip. It returns whatever ip results from a DNS lookup of `host-subdomain.mydomain.com`. I picked `192.168.1.200` as an example; when reading the answer replace that with whatever address is appropriate. You didn't indicate that address in your question so I had to pick something.
Nuno avatar
us flag
Thanks for clarifying. No problem (in my original question, I said it was a public IP :-)). I believe I understand what you're trying to say. However, I'd have thought that once it's a public IP, it would use the external network interface (e.g. eth1, based on the route table), even if it's bridged through the host. So the caller's IP address would be the Host's public IP.
pt flag
Your container has a private ip address. It's connecting to an address on the host. There is no step in this process that will transform the container ip address into some other address. Your host is directly connected to the container network.
Nuno avatar
us flag
"It's connecting to an address on the host." - I understand, but neither the Container or the Host knows that. "ping host-subdomain.mydomain.com" returns the public IP. So unless there's something in the Docker-Host interaction that checks "is the IP address the same as the Host's? then use internal network", it doesn't make sense to me. If the Container connects to another Host, that Host's code wouldn't see the private IP.
Nuno avatar
us flag
In the container, "ping" doesn't exist, but `curl -sI -w '%{remote_ip}' host-subdomain.mydomain.com` prints the public IP as per the A record in the DNS, as expected. I'm still not understanding how the container's private IP gets there in the end!!
pt flag
I'm not sure how else I can explain this: you see the container's ip in the host logs because that is the address from which the connection originates. This is just basic ip routing: your container has a route to the public ip via its default gateway (which is a bridge interface on the host).
Nuno avatar
us flag
Thank you. I see your last Edit. I appreciate your time on this. I guess the reason is that once the Host sees the request coming from `br-1234`, and it sees it's the IP of the Host itself, the request doesn't leave the Host at all, so that's why it uses the private IP of the container. So the request really never goes through the Internet and come back. Cheers!
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.