Inter-container connection via localhost - docker

I would like to set up my containers so that they connect to each other via localhost.
My setup is a main application container and two other containers that it needs to connect to (ActiveMQ and Wiremock).
I already run ActiveMQ and Wiremock in containers with the relevant ports exposed, and the main application runs through IntelliJ and connects to these. However, when I am not developing the main applications, I would like to run it in a container for simplicity but it cannot connect to the ports exposed by the others.
Setting --net=host doesn't seem to work, nor does creating a network docker network create <NAME> and assigning it in the docker run with --net=<NAME>.
The application already runs in a container in other environments on the host network.

docker creates a default network in which all containers run, and sets a network name for each of your containers, using the container name.
if you have a contained named mq for your ActiveMQ, then you would use something like tcp://mq:61616 (or whatever protocol / port you have configured) from your other containers, to connect to it.
you shouldn't need to set the --net option unless you need to create a specific network for specific containers to use.

Related

Connect windows containers to docker host network

Context, I'm currently dockerizing an application in windows containers, the application
will connect to a Sql Server database from outside the container, normally working with linux containers I could use host driver, but since that is not available in windows containers. How could I connect to that database outside my windows container?
So, the answers provided before are all valid. I'd just add that while Host network is not available on Windows, you can still use the same concept - albeit a bit different.
The native network driver on Windows is Network Address Translation. With that driver, the container will get a private IP address and the ports from the container host can be mapped to the ports on the container, by use of the docker run -p 8080:80, for example.
That way, if you want to continue to use the option to call the localhost between the app container and the database container you can. You just need to specify the port: localhost:8080. Note that if the host is not using that port, you can even map it directly, such as: docker run -p 80:80. The caveat here is: The container host cannot be using the port already, and you can't map the same port to another container. So, if you need another instance, you can map to something like: docker run -p 81:80.
I blogged about this here: https://cda.ms/4nB

docker container networking to connect localhost in one container to another

I am using the default bridge network for docker (and yes, I am relatively new to docker). I have two docker containers.
The first container provides a service on port 12345. When creating this container, I did not specify the --publish option because I did not want to expose this port to the outside world.
The second container needs to use the service from the first container. However, the application running in this second container was hardcoded to access the service at 127.0.0.1:12345. Clearly, the second container's localhost is not the same as the first container. Is there a way to course docker networking to think that localhost in the second container should actually be connected to the port in the first container, without exposing anything to the outside world?
Option N: (this works but may not be the best solution)
One way you can force this to behave the way you need is through injecting an additional service to bind to the port within on the application container and redirecting it outward.
socat TCP-LISTEN:12345,fork TCP:172.18.0.2:12345
A quick test here, I was able to confirm 127.0.0.1:12345 is treated as the remote 12345
Things to consider:
The two containers needs to be able to reach each other
It breaks the recommendation of one service per container.
Getting the app into the docker container. (yum / apt-get install socat, source build = ?)
Getting it to run on startup on container start/restart.

Choosing range of ports in spark

From spark documentation I know that the ports that executors, i.e. workers (because by default there is just one executor per a worker) use for establishing connection with master are randomly determined, but how could I setup their range to publish those ports in docker. Also, if a worker establishes a connection with another container (which is not part of the distributed system), do I need to publish the port on which the worker would get returned data from the container (e.g. via an https request)?
Just to note, I do not use docker-compose.yml because I do not need the containers to be set as services and I want to add/remove containers when needed by increase/decrease in number of customers.
You should use the same docker network for all containers which will communicate with each other. Containers can reach others using container name (on all ports) just like if different hosts on a network.
Create a network (needed only once)
docker network create <network_name>
when you launch a container use --network to connect container to the network
docker run --network=<network_name> --name <container_name> <image>
You can also connect existing containers to networks
docker network connect <network_name> <container_name>
Reference:
https://docs.docker.com/engine/reference/commandline/network_create/
https://docs.docker.com/engine/reference/run/

How to use confluent/cp-kafka image in docker compose with advertising on localhost and my network container name kafka?

How to use confluent/cp-kafka image in docker compose with exposing on localhost and my network container name kafka?
Do not link this as duplicate of:
Connect to docker kafka container from localhost and another docker container
Cannot produce message to kafka from service running in docker
These do not solve my issue because the methods they use are depreciated by confluent/cp-kafka and I want to connect on localhost and on the docker network.
In the configure script on confluent/cp-kafka they do this annoying task:
# By default, LISTENERS is derived from ADVERTISED_LISTENERS by replacing
# hosts with 0.0.0.0. This is good default as it ensures that the broker
# process listens on all ports.
if [[ -z "${KAFKA_LISTENERS-}" ]]
then
export KAFKA_LISTENERS
KAFKA_LISTENERS=$(cub listeners "$KAFKA_ADVERTISED_LISTENERS")
fi
It always sets whatever I give KAFKA_ADVERTISED_LISTENERS to 0.0.0.0! Using the docker network, doing
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9093,PLAINTEXT://kafka:9093
I expect the listeners to be either localhost:9092 or 0.0.0.0:9092 and some docker ip PLAINTEXT://172.17.0.1:9093 (whatever kafka resolves to on the docker network)
Currently I can get only one or the other to work. So using localhost, it only works on the host system, no docker containers can access it. Using kafka, it only works in the docker network, no host applications can access it. I want it to work with both. I am using docker compose so that I can have zookeeper, kafka, redis, and my application start up. I have other applications that will startup without docker.
Update
So when I set PLAINTEXT://localhost:9092 I can access kafka running docker, outside of docker.
When I set PLAINTEXT://kafka:9092 I cannot access kafka running docker, outside of docker.
This is expected, however doing this: PLAINTEXT://localhost:9092,PLAINTEXT://kafka:9093 I would expect to access kafka running docker, both inside and outside docker. The confluent/cp-kafka image is wiping out localhost and kafka. Setting them both to 0.0.0.0, then throwing an error that I set 2 different ports to the same ip...
Maybe I'm just clashing into some opinionated docker image and should look for a different image...
Maybe I'm just clashing into some opinionated docker image and should look for a different image...
The image is fine. You might want to read this explanation of the listeners.
tl;dr - you don't want to (and shouldn't?) use the same listener "protocol" in different networks.
Use the advertised.listeners, no need to edit the listeners
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://broker:9092,PLAINTEXT_HOST://localhost:29092
When PLAINTEXT://localhost:9093 is being loaded inside of the container, you need to add port mappings for 9093, which should be self explanatory, and you connect to localhost:9093 and it should work.
Then, if you also had PLAINTEXT://kafka:9092, that will only work within the Docker Compose network overlay, not externally to your DNS servers, because that's how Docker networking works. You should be able to run other applications as part of that Docker network with the --network flag, or link containers using Docker Compose
Keep in mind that if you're running on Mac, the recommended way (as per the Confluent docs) is to run these containers in Docker Machine, in a VM, where you can manage the external port mappings correctly using the --net=host flag of Docker. However, using the blog above, it all works fine on a Mac outside a VM.

Cross container communication with Docker

An application server is running as one Docker container and database running in another container. IP address of the database server is obtained as:
sudo docker inspect -f '{{ .NetworkSettings.IPAddress }}' db
Setting up JDBC resource in the application server to point to the database gives "java.net.ConnectException".
Linking containers is not an option since that only works on the same host.
How do I ensure that IP address of the database container is visible to the application server container?
If you want private networking between docker containers on remote hosts you can use weave to setup an overlay network between docker containers. If you don't need a private network just expose the ports using the -p switch and configure the addresses of the host machine as the destination IP in the required docker container.
One simple way to solve this would be using Weave. It allows you to create many application-specific networks that can span multiple hosts as well as datacenters. It also has a very neat DNS-based service discovery mechanism.
I should disclaim, I am one of Weave engineering team.
Linking containers is not an option since that only works on the same host.
So are you saying your application is a container running on docker server 1 and your db is a container on docker server 2? If so, you treat it like ordinary remote hosts. Your DB port needs to be exposed on docker server 2 and that IP:port needs to be configured into your application server, typically via environment variables.
The per host docker subnetwork is a Private Network. It's perhaps possible to have this address be routable, but it would be much pain. And it's further complicated because container IP's are not static.
What you need to do is publish the ports/services up to the host (via PORT in dockerfile and -p in your docker run) Then you just do host->host. You can resolve hosts by IP, Environment Variables, or good old DNS.
Few things were missing that were not allowing the cross-container communication:
WildFly was not bound to 0.0.0.0 and thus was only accepting requests on eht0. This was fixed using "-b 0.0.0.0".
Firewall was not allowing the containers to communication. This was removed using "systemctl stop firewall; systemctl disable firewall"
Virtual Box image required a Host-only adapter
After this, the containers are able to communicate. Complete details are available at:
http://blog.arungupta.me/2014/12/wildfly-javaee7-mysql-link-two-docker-container-techtip65/

Resources