Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access Docker container's internal IP address from host?

I have 2 docker containers running on my Mac host - container 1 is Jenkins from Docker Hub and container 2 is SonarQube from Docker Hub. I have both containers running successfully. I can access Jenkins from my host by going to http://localhost:8080/ and I can access my SonarQube by going to http://localhost:9000/.

The Jenkins container was started like this:

docker run -d -p 8080:8080 -p 50000:50000 jenkins/jenkins:latest

The SonarQube container was started like this:

docker run -d -p 9000:9000 sonarqube

Now I want to have each container communicate with each other so I need to provide the IP address of the other container to each container.

I got the IP address of each container by executing this:

docker inspect --format '{{ .NetworkSettings.IPAddress }}' container_name_or_id

This returns an IP address of 172.17.0.2 for the Jenkins container and 172.17.0.3 for the SonarQube container. But when I try and access the Jenkins container from my host by going to http://172.17.0.2:8080 I get a request timeout. The same thing happens when I try and access the SonarQube container from my host by going to http://172.17.0.3:9000

Is this normal behavior?

Shouldn't I be able to access each container from my host by their internal IP address?

And how can I test that one container (e.g. Jenkins) can access the other container (e.g. SonarQube) by IP address?

like image 959
gomisha Avatar asked Jan 01 '19 00:01

gomisha


2 Answers

Looks like you are using default bridge network model. Internal IPs are meant for each container to talk to each other under bridge networking. You cannot access them from host.

There are multiple options for you.

  1. You can configure http://172.17.0.3:9000 as your sonar endpoint in Jenkins.
  2. You can configure http://172.17.0.2:8000 as your jenkins endpoint in sonar.
  3. If you don't want to hard code above Ips then both of your containers can talk to each using Docker Default GatewayIp(172.17.0.1) and their internal port. so essentially you can configure http://172.17.0.1 as well.

Note - Default Gateway Ip change change if you define user defined bridge network.

https://docs.docker.com/v17.09/engine/userguide/networking/#the-default-bridge-network

https://docs.docker.com/network/network-tutorial-standalone/

If you want to spin up both containers using docker-compose, then you can link both containers using service name. Just follow Networking in Compose.

like image 157
Imran Avatar answered Oct 13 '22 01:10

Imran


Is this normal behavior? Shouldn't I be able to access each container from my host by their internal IP address?

What you describe is normal behavior: you can't directly reach the Docker-internal IP addresses from a MacOS host. See "Per-container IP addressing is not possible" in the Docker for Mac docs.

How can I test that one container (e.g. Jenkins) can access the other container (e.g. SonarQube) by IP address?

This isn't something I normally "test" per se. Start up both processes and have them make their normal (HTTP) connections; if it works you'll see appropriate log messages, and if it doesn't work you'll see complaints. (Getting a root shell in a container to send ICMP packets from one container to another seems to be a popular option but doesn't prove much.)

Also: don't make this connection by explicit IP address. As you've noticed already the Docker-internal IP addresses aren't usable in some contexts, and they'll change whenever you restart containers. Instead, Docker provides an internal DNS service that can resolve host names when communicating between containers, but you need to explicitly set up a non-default bridge network. That setup would look like:

docker network create jenkinsnet
docker run --name sonarqube -d --net jenkinsnet \
  -p 9000:9000 \
  sonarqube
docker run --name jenkins -d --net jenkinsnet \
  -p 8080:8080 -p 50000:50000 \
  -e SONARQUBE_URL=http://sonarqube:9000 \
  jenkins/jenkins:latest

So I've explicitly created a network; started both containers connected to it; and told the client container (via an environment variable) where the server container is. You don't have to publish ports with docker run -p to reach them this way; whether you do or not, use the port the server process is listening on (the second port number in the docker run -p option).

From the host, your only (portable, reliable) path to reach the container is via its published ports.

like image 29
David Maze Avatar answered Oct 12 '22 23:10

David Maze