Docker container - Couchbase server node internal IP address - docker

I have created docker container for Couchbase. The service is up and running but with the following command,
couchbase-cli cluster-init -c $CB_SERVER_IPADDR:8091 --cluster-init-username=admin --cluster-init-password=couchbase --cluster-init-ramsize=2048
I get a server node in couchbase with the name as its internal IP address - 172.x.x.x. Then when i create bucket using the following command,
couchbase-cli bucket-create -c $CB_SERVER_IPADDR:8091 -u admin -p couchbase --bucket=heartbeat --bucket-type=couchbase --bucket-ramsize=500 --bucket-replica=0 --wait
buckets gets created. But when my web application which is in a different container, communicates with couchbase with the IP address of the docker host where the Couchbase server is running, i get the following error message
2014-08-05 21:49:00.106 INFO com.couchbase.client.CouchbaseConnection: Reconnecting due to exception on {QA sa=172.x.x.x/172.x.x.x:11210, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0}
java.net.NoRouteToHostException: No route to host
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:739)
at net.spy.memcached.MemcachedConnection.handleIO(MemcachedConnection.java:485)
at net.spy.memcached.MemcachedConnection.handleIO(MemcachedConnection.java:322)
at com.couchbase.client.CouchbaseConnection.run(CouchbaseConnection.java:288)
I could see that my application is using the server node name which is the internal IP address to communicate with the couchbase and thus the error. Any help appreciated

Your web application docker container is not able to resolve the host name of the couchbase docker container.
You would need to link the web application container and couchbase container together.
Below will create a name "couchbase" for your couchbase instance, this name will later be referenced by web application docker container
sudo docker run -d --name couchbase <your couchbase image name>
Below will add an entry "$your_couchbase_docker_container_IP couchbase" into /etc/hosts on your web application docker container
sudo docker run -d -P --link couchbase:couchbase <your web application image name>
Then in your web application, you can use couchbase:8091 to access the couchbase docker container
More detail on "docker link" is available at https://docs.docker.com/userguide/dockerlinks/

Related

I can't access my Docker container on GCP Compute Engine

I have my Docker container running on GCP Compute Engine. The CE server is running on CentOS 7. My Docker container has the application being served by Nginx with port 80 exposed. For some reason, I can't access it from the external IP address on my browser.
I ran the container with this command:
sudo docker run --name myapp -p 80:80 -d myapp:1.0.0
When I do sudo curl <internal_ip>:80 or sudo curl <localhost>:80 it will show that the application is running and returns back the content, but if I try to access in my browser with <external_ip>:80, it doesn't load anything. What can I do to make this accessible through the external IP address?
It seems I had to configure the firewall to open up port 80.

How to access a port that is already used by another Docker container

I am running a Tomcat server on one Docker container. On another docker container, i want to be able to access that Tomcat server. So, what I do is to use the -p option to map that port to the port mapped by the Docker container running the Tomcat server.
In short, I have the Tomcat container, which was run using something like this.
docker run ... -p X:8080 ...
And the other docker container like this
docker run ... -p X:X ...
However, if I try to do so, I get "Port is already allocated" error. How can I solve this problem?
When you add -p X:Y you are mapping Y port from container to X port in host machine and making it accessable in host.
Lets assume your tomcat container is running on 8080:8080
Now you have another container running
You can access tomcat container inside 2nd container by internal IP.
If both containers are on default network.
Something like this 172.0.0.2:8080
You can get assigned internal IP for container by this
docker network inspect bridge
or
docker container inspect $id
where id is container id

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?
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.
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.
You can configure http://172.17.0.3:9000 as your sonar endpoint in Jenkins.
You can configure http://172.17.0.2:8000 as your jenkins endpoint in sonar.
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.
The accepted answer (https://stackoverflow.com/a/53992787/7730554) already provides valid options of which I personally usually prefer using docker compose.
But as you are running Docker on Mac you could also use host.docker.internal in combination with the defined forwarding host port. So Docker will take care that host.docker.internal is resolved to the corresponding IP even if your Host IP changes.
See https://docs.docker.com/desktop/mac/networking/.
Note that this is for development mode only and works when you use Docker Desktop.

How do I configure docker to allow a connection to a container from other computers?

I am trying to run a small test server with MS SQL Server running on a Mac in a Linux docker container. Maybe I have the terminology wrong so please correct me if necessary:
host - the macOS desktop with docker installed (ip 10.0.1.73)
container - the Linux instance running in the docker container with SQL Server running in it
remote desktop - another computer on the local area network trying to connect to SQL Server
I followed the MS installation instructions and everything seems to be running fine, except I can't connect to SQL Server from the Remote Desktop
I can connect to the docker host(10.0.1.73) and can ping the IP address
I can connect to SQL Server from the docker host and see the databases etc.
I used the following command to create the docker container
sudo docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=<XXXXXX>" -p 1433:1433 --name sqlserver1 -d microsoft/mssql-server-linux:2017-latest
Thinking that the -p 1433:1433 would map the linux port to the macOS host port and allow the remote computer to access the docker container when connecting to that port on the macOS host from the local area network
This is not working and I assume this may be to do with the network routing on the macOS host
Most solutions I have seen seem to indicate that one should use the VirtualBox UI to modify the network settings - but I don't have that installed
The others seem to have pages and pages of command line instructions that are required
Is there an easy solution somewhere I have missed?
EDIT:
Some more research and I found this explanation about how by default the Docker networking is set up for single host networking. Good explanation for anyone else struggling with the Docker concepts.
It is also worth reading up about the differences between docker containers and virtual machines...
https://youtu.be/Js_140tDlVI
Still trying to find some explanation on multi host networking.
try disabeling the firewall on the host you want to connect to.
port 1433 will be forwarded to the docker container, but your host (MAC) should have port 1433 open to be able to connect to your host.
Using NAT:
Assign the target address to your host interface:
sudo ifconfig en1 alias 10.0.1.74/21 up
Create the docker container and map the port to the second IP address assigned to the host interface
sudo docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=<XXXXXXXXX>" -p 10.0.1.74:1433:1433 --name sqlserver1 -d microsoft/mssql-server-linux:2017-latest

connecting tomcat webapp running in docker container to mysql

I have mysql server running in centos host and I want to deploy my war in tomcat inside docker container in same host. Any idea how can I connect mysql from inside the container.
Here is what you can do to connect to the DB (mysql) from the App (tomcat).
There are two ways you can do this
By using links
Manual way by providing the IP address of db to the tomcat app
Example-1 (Links)
Get your mysql container up:
"docker run --name db -e MYSQL_ROOT_PASSWORD="xxxx" -e
MYSQL_DATABASE="xxxx" -d mysql"
You now need to build and run the application container which must
know where is the db instance. You will have to figure out where you
provide the link to the db in your application. It can be in the code
or in a property file. You can use volume to mount this file into the
application container. You will also be able to modify them on the
fly because they will be accessible to you on the host system. This
is one example of doing this: docker
docker run -d -p 8080:8080 --name app --link db:db -v
$PWD/webapp:/var/lib/tomcat7/webapps/ app
Here we are using the image app where i am mounting webapp folder
from my docker base folder. This folder is having my code which i am
pushing to the tomcat's webapp folder. I am also pushing the
properties file to the appropiate location on the container where the
mysql connection is mentioned like this :
"jdbc.url=jdbc:mysql://db:3306/dbname" . We are mapping port 8080 of
the container to the port 8080 of the host. We are mapping container
db with container app. This creates an entry on /etc/hosts file - "db
ipname". So both containers can communicate with each other even if
we restart the db container (which changes the IP). Links will update
the host entry with the new IP.
Example 2:
Up the db container
Get the IP of the db container using this "docker inspect -f '{{ .NetworkSettings.IPAddress }}' container-name/ID"
Up the app containers with volumes where you can edit the jdbc url on your host.
Change the IP to db container's IP and this should be able to establish the connection
If you want to use Host's mysql
docker run -d --net=host --name app image command
Do let me know if you need any further explanation.
You can go through the topics on volumes, links from docker documentation: https://docs.docker.com/

Resources