Unable to communicate between docker containers - docker

We are running two docker containers with network as host for each container, We are able to communicate to container from outside world, but we are not able to communicate between the containers.
Is there a way to configure docker network so that containers can communication among themselves as well as outside world.

When you configure a docker container to use "host" networking, you completely remove the docker networking stack, including the container to container networking and built in dns discovery. Everything you see in the container's network is identical to what you see on the host. So another container listening on localhost is visible on 127.0.0.1 from the host and from other containers with host networking.
This is not the recommended way to run docker containers in most scenarios. You typically create a docker network for a group of containers, start those containers on that docker network, and then refer to the other containers by their container name.

Found a solution to my question, I am able to communicate between containers using docker0 network (default network), and to map select ports of container to outside world I am using -p mapping to map from container port to host port.
as #BMitch suggested a separate network to connect only the containers that need inter container comm is better than using docker0 as all containers without any explicit network configuration connect to docker0.

Related

Why is Docker container able to access the internet?

I have a basic question about Docker that is probably due to lack of knowledge on my part about networking. The Docker container networking documentation states:
By default, when you create a container, it does not publish any of its ports to the outside world. To make a port available to services outside of Docker, or to Docker containers which are not connected to the container’s network, use the --publish or -p flag. This creates a firewall rule which maps a container port to a port on the Docker host.
It sounds like, when you install a container on your computer without mapping any ports from the container to the host machine, the container should not be able to access the internet. However, for example, I install the Ubuntu container with:
docker pull ubuntu
Then I enter the container's command line with:
docker run -ti ubuntu bash
At that point, I can run apt-get update and the container starts pulling information from the internet without mapping any ports (e.g. -p 80:80). How is this possible?
Publishing a port allows machines external to the docker host to access the container, inbound connectivity. By default, containers can access the network with outbound connectivity.
To restrict a container from accessing the network, you can either run the container with no network (note: this still creates a loopback interface, and you can later connect it to another network):
docker run --net none ...
Or you can create a network with the --internal option and run containers on that network:
docker network create --internal internal
docker run --net internal ...
The internal network is created without a gateway interface on the bridge network.
When they talk about publishing ports, they mean inbound ports.
Outbound ports work - depending on your network type - see here for more:
https://docs.docker.com/network/

difference between docker BRIDGE and HOST driver?

Can you give me one guide or graph to understand the difference?
The reason why I ask this question is I can't open website with the following method:
docker network create -d bridge mybridge
docker run -d --net mybridge --name db redis
docker run -d --net mybridge -e DB=db -p 8000:5000 --name web chrch/web
But I can open website with the following method:
docker run --rm -d --network host --name my_nginx nginx
I use google cloud platform VM instance and install docker by myself.
According to the docker documentation about bridge networking:
In terms of Docker, a bridge network uses a software bridge which allows containers connected to the same bridge network to communicate, while providing isolation from containers which are not connected to that bridge network.
According to the docker documentation about host networking
If you use the host network driver for a container, that container’s network stack is not isolated from the Docker host. For instance, if you run a container which binds to port 80 and you use host networking, the container’s application will be available on port 80 on the host’s IP address.
If you want to deploy multiple containers connected between them with a private internal network use bridge networking. If you want to deploy a container connected to the same network stack as the host (and access the same networks as the host) use host networking. If you simply want to publish some ports, run the container with the --publish or -p option, such as -p 8080:80.
In your first example I'd expect the application to be reachable on the host's IP address at port 8000 (the remapped port), and in the second port 5000 (there is no remapping option with host networking). If there's some sort of configuration or firewalling issue preventing this from working you should address that, rather than hack around it with --net host.
Bridge networking is Docker's standard networking mode. You should prefer it if at all possible. There are, confusingly, two different modes of it, but the form you show with an explicit docker network create is a best practice and you should use it if at all possible. Host networking completely disables Docker's network isolation. It means containers see and use exactly the same network interfaces the host has available, without an intermediate NAT layer.
With bridge networking, you need the docker run -p option to make specific ports visible outside of Docker. As an operator you can remap ports, bind to specific interfaces on a multi-homed system, or simply decline to make a service visible to other hosts at all. The explicit docker network create form lets containers connect to each other using their docker run --name as host names. If you're running multiple application stacks on the same host, they can be partially isolated from each other by using separate networks. Each container has its own separate network space, and localhost means "this container". This mode is also an easy step to the networking models in multi-host systems like Docker Swarm or Kubernetes.
With host networking, none of the above works at all; you cannot use docker run --net host -p ... and you have no choice about where or how ports are exposed. You can't reach other containers, unless they're configured to publish ports themselves. Since you're using the host's network, localhost means the host's view of itself.
For all that it's frequently recommended in SO answers, --net host is rarely necessary. The two cases I can think of off hand are for a service that needs to interrogate the host's network stack (for instance, a service-discovery system like Consul needs to know every port the host is listening on to advertise that) or for a service that has a large or inconsistent set of ports it uses. If you're using --net host because you've hard-coded localhost in your application, you're better off making that configurable..
Feature
Bridge
Host
Driver
The Bridge network is provided by the Bridge driver
The host network is provided by the host driver.
Default
bridge is the default network and provided by a bridge driver
Host does not default.
Connectivity
The bridge driver provides intercontainer connectivity for all containers running on the same machine.
The host driver instructs Docker not to create any special networking namespace or resources for attached containers.

communicate with a service inside a docker from the host without using it's IP

I have a process running on a host that needs to communicate with a docker and I want it to be done by some parameter that can't change (like docker name or host name) unlike IP (prefer not to make the IP of the docker static or install external dockers for this).
I'm aware that dockers can resolve addressees by name in a private network and that's what I want but not between dockers but between process running on the host and docker.
couldn't find a solution, can it be done ?
Edit:
I'm not allowed to use host network and open additional ports on the host for security reasons.
You're welcome to choose the way which fits your needs better.
Option 1. Use host's networking. In this case Docker does not create separate net for container and you connect to container's services as if they would run on your host:
docker run --network=host <image_name>
Drawback of this approach - low isolation and thus security. You dont need to expose any ports here - if service listens on 8080, just open localhost:8080 and enjoy.
Second approach is more correct - you expose (somehow forward) internal ports in container and map them onto ports in the host.
docker run -p 8080:80 <image_name>
This will map port 80 from container to port 8080 on the host. As in previous example, you still connect using localhost, e.g. localhost:8080.

How to specify IP of docker container in Marathon?

We can map docker container port to host machine IP and port using
docker run -d -p <some-ip>:<port>:<port> --name <some-name> <docker-image>
But how to specify host machine IP while deploying the same container using Marathon? Where should I specify the IP of host machine in Marathon app spec? For my requirement specifying host IP is a necessity.
You can use Marathon constraints to influence the placement of your app but I'd suggest that a better, more forward-looking way is not to pin an app to a certain node (what if this node fails?) but use service discovery to dynamically figure out the IP and the port the app is serving on.

Host-only network for Docker container

When running a Docker container, I'd like to set up the container's network so that the container is only able to communicate with the host on the (TCP) ports that the host is listening to. I don't want the container to have access to the internet, or other containers running on the same host, or to the network that the host is connected to. If I was running a VM with something like VMWare, I would choose the "host-only" networking option which creates a private network between the guuest VM and the host with the properties described above.
I've looked into using Docker's --net=none but I don't know what direction to go with to configure the network to achieve my goals. TAP/TUN seems to be the way to go, but I'd appreciate some direction
You could create --internal network and run a container inside it.
Creating a network:
docker network create -d bridge --internal hostonly
Running a container:
docker run --network hostonly ...
Potential partial answer:
If you can use a unix socket to communicate with your application instead of TCP, then you could use
docker run -net=none -v /host-path/socket.sock:/container-path/socket.sock
to provide direct communication between the container and the host socket, without allowing any networking out of the container.

Resources