For regular docker containers (say the hello world example), after you run it, it is accessible thought localhost, where you can make a request it through your browser.
But sometimes it seems to access a container you need a special IP address. I'm wondering what's this behavior of docker container networking called and where is it defined/documented.
Let's say my local ip address is 10.0.75.1 (got from Network properties in Windows settings named, vEthernet (DockerNAT)). But in order to connect to a container running I had to use ip address 10.0.75.2. Why is this?
If try to inspect existing docker networks using docker network [cmd], the containers seem to be on different subnets, for example '172.17.0.0/16'
Related
Here is my situation:
First,I run a MySQL container(IP:172.17.0.2) on centOS;
Then I run a Nacos contanier with specified datasource(MySQL above) on the same host, but i didn't use the ip of the MySQL container, instead I used the ip of the bridge Gateway(172.17.0.1)(two containers both link to the default bridge).
What surprised me was that Nacos works well, it can query config data from MySQL container normally.
How did this happen? I have read some documention but didn't get the answer.It really confused me.
On modern Docker installations, try to avoid using the default bridge network. docker network create a network (it doesn't need any special options, but it does need to be created) and then launch your containers on --net that network. If you're using Compose, it creates a ("user bridge") network named default for you.
On your CentOS host, if you run ifconfig, you should see a docker0 interface with the 172.17.0.1 address. When you launch a container with the docker run -p option, that container is accessible via the first port number on all host interfaces, including the docker0 interface.
Meanwhile, inside a container (on the default bridge network), it sees that same IP address as the normal IPv4 gateway address (try docker run --rm busybox route -n). So, when you connect to 172.17.0.1:3306, you're connecting out to the host, and then connecting to the published port of the database container.
This isn't a totally standard way to connect between containers, though it will work. You should prefer using Docker named networks, which will let you connect to another container using the container's name without manually doing any IP-address lookups. If you really can't move off of the default bridge network, then the standard approach is to --link to the other container, but this entire path is considered outdated.
I am using docker container for my asp.net core web api application and container is up and running.
Now I am getting docker internal IP address using below command,
docker inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" d986472784cb and getting the IP address as 172.20.0.2.
Now I am not getting any result when hitting below url in browser
http://172.20.0.2/WeatherForecast, seeing ERR_CONNECTION_TIMED_OUT error.
local address https://localhost:32772/weatherforecast is just working fine.
What could be the issue?
The container-private IP simply doesn't work in a variety of common circumstances:
If you're not calling from the same host, the container-private IP won't be reachable at all
If there is a VM involved at all (Docker Toolbox on Windows, Docker Desktop on Windows or Mac), the container-private IP won't be reachable at all
If you're not on the same Docker-internal network, you might not be able to reach the container-private IP
Since it doesn't work in so many environments, I wouldn't recommend looking up this IP address at all: forget that particular docker inspect command exists. From the browser, use your host's IP address or DNS name (or localhost if the containers and browser are on the same system, but not if Docker Toolbox is involved) and the published port number (docker run -p option, Docker Compose ports: option, the first port number from that pair).
You need the port number in the ip address url. http://172.20.0.2:32772/WeatherForecast
I am using Docker desktop, I have a couple of docker containers running using docker-compose and port forwarding. I can access the containers from my mac using localhost. On the second container, I am exposing on different ports. I can see ip addresses are associated to both containers by using docker inspect, but I cannot access using the ip address.
I would like access the container from my local mac by
dns domain
ip address
Any help appreciated.
Thanks
You cannot directly connect to the container-private IP addresses on MacOS. You also can't connect to them using a VM-based Docker implementation like Docker Toolbox or Kubernetes' minikube, or from a different host. Looking up and using these IP addresses, or trying to manually set them, usually isn't a best practice.
Instead you can use the docker run -p option to publish a port from your container to the host. Programs running directly on the host can access the container using localhost as a host name and the published port number. This works on all platforms; on VM-based solutions use the VM's IP address instead of localhost; from a different host, use the Docker host's DNS name or IP address.
I deployed a demo web API project on port 8086.I am able to run it on my local browser using localhost:8086/api/controllername and also using local machine IP address for example: 192.0.0.0:8086/api/controllername. I tried accessing the URL from another machine on same LAN and I am able to access it.
But now I want to access it from machines on other networks (publicly).
How can I assign a static IP so that I can use the API from any machine irrespective of network? I created a network using below commands
docker network create --driver bridge --subnet 172.18.0.0/16 -- gateway=172.18.0.1 IPStatic
and
docker network connect --ip 172.18.0.2 IPStatic Containerid.
But unable to access the api using 172.18.0.2:8086/api. Am I missing something? I am using asp.net core web api and I am fairly new to Docker.
You always use the host IP address for this, the same way as if you were running the service outside of Docker. The container-private IP addresses are unreachable from other hosts (and on some platforms aren't even reachable from outside Docker on the same host); it's usually wrong to manually set them or to try to look them up.
If it's specifically important that this service have its own IP address, you need to ask your network administrator to assign an additional address to the host. The docker run -p option can bind a service to only specific network interfaces or addresses. On a Linux host I might run
# Assign the alias address
ifconfig eth0:0 192.0.0.2
# Run the service bound to only this interface
docker run -p 192.0.0.2:80:8080 ...
You might need to reconfigure other services to not listen on this new interface. For Docker services you'd use the same docker run -p option to bind to only the host's primary interface and to localhost (127.0.0.1); configuration for non-Docker services is specific to the service.
i want to expose the container ip to the external network where the host is running so that i can directly ping the docker container ip from an external machine.
If i ping the docker container ip from the external machine where the machine hosting the docker and the machine from which i am pinging are in the same network i need to get the response from these machines
Pinging the container's IP (i.e. the IP it shows when you look at docker inspect [CONTAINER]) from another machine does not work. However, the container is reachable via the public IP of its host.
In addition to Borja's answer, you can expose the ports of Docker containers by adding -p [HOST_PORT]:[CONTAINER_PORT] to your docker run command.
E.g. if you want to reach a web server in a Docker container from another machine, you can start it with docker run -d -p 80:80 httpd:alpine. The container's port 80 is then reachable via the host's port 80. Other machines on the same network will then also be able to reach the webserver in this container (depending on Firewall settings etc. of course...)
Since you tagged this as kubernetes:
You cannot directly send packets to individual Docker containers. You need to send them to somewhere else that’s able to route them. In the case of plain Docker, you need to use the docker run -p option to publish a port to the host, and then containers will be reachable via the published port via the host’s IP address or DNS name. In a Kubernetes context, you need to set up a Service that’s able to route traffic to the Pod (or Pods) that are running your container, and you ultimately reach containers via that Service.
The container-internal IP addresses are essentially useless in many contexts. (They cannot be reached from off-host at all; in some environments you can’t even reach them from outside of Docker on the same host.) There are other mechanisms you can use to reach containers (docker run -p from outside Docker, inter-container DNS from within Docker) and you never need to look up these IP addresses at all.
Your question places a heavy emphasis on ping(1). This is a very-low-level debugging tool that uses a network protocol called ICMP. If sending packets using ICMP is actually core to your workflow, you will have difficulty running it in Docker or Kubernetes. I suspect you aren’t actually. Don’t worry so much about being able to directly ping containers; use higher-level tools like curl(1) if you need to verify that a request is reaching its container.
It's pretty easy actually, assuming you have control over the routing tables of your external devices (either directly, or via your LAN's gateway/router). Assuming your containers are using a bridge network of 172.17.0.0/16, you add a static entry for the 172.17.0.0/16 network, with your Docker physical LAN IP as the gateway. You might need to also allow this forwarding in your Docker OS firewall configuration.
After that, you should be able to connect to your docker container using its bridge address (172.17.0.2 for example). Note however that it will likely not respond to pings, due to the container's firewall.
If you're content to access your container using only the bridge IP (and never again use your Docker host IP with the mapped-port), you can remove port mapping from the container entirely.
You need to create a new bridge docker network and attach the container to this network. You should be able to connect by this way.
docker network create -d bridge my-new-bridge-network
or
docker network create --driver=bridge --subnet=192.168.0.0/16 my-new-bridge-network
connect:
docker network connect my-new-bridge-network container1
or
docker network connect --ip 192.168.0.10/16 my-new-bridge-network container-name
If the problem persist, just reload docker daemon, restart the service. Is a known issue.