Thursday, June 24, 2021

Communicating between docker containers

In the real world, beyond the realm of the simple hello-world tutorial, running just one container isn’t enough for most apps. A modern application typically consists of a few components – such as a database, a web server, or some microservices.


How to do simple communication between Docker containers, when they are running on the same host (which is sometimes called single-host networking).

Although containers have a level of isolation from the environment around them, they often need to communicate with each other, and the outside world.


Two containers can talk to each other in one of two ways, usually:


Communicating through networking: Containers are designed to be isolated. But they can send and receive requests to other applications, using networking.

For example: a web server container might expose a port, so that it can receive requests on port 80. Or an application container might make a connection to a database container.


Sharing files on disk: Some applications communicate by reading and writing files. These kinds of applications can communicate by writing their files into a volume, which can also be shared with other containers.



Communication between containers with networking

For example, an application might call a REST or GraphQL API, or open a connection to a database.

Containers are ideal for applications or processes which expose some sort of network service. The most well-known examples of these kinds of applications are:

  • Web servers - e.g. Nginx, Apache
  • Backend applications and APIs - e.g. Node, Python, JBoss, Wildfly, Spring Boot
  • Databases and data stores - e.g. MongoDB, PostgreSQL


If you are running more than one container, you can let your containers communicate with each other by attaching them to the same network.

Docker creates virtual networks which let your containers talk to each other. In a network, a container has an IP address, and optionally a hostname.

You can create different types of networks depending on what you would like to do. 


  • The default bridge network, which allows simple container-to-container communication by IP address, and is created by default.
  • user-defined bridge network, which you create yourself, and allows your containers to communicate with each other, by using their container name as a hostname.


The simplest network in Docker is the bridge network. It’s also Docker’s default networking driver.

A bridge network gives you simple communication between containers on the same host.


When Docker starts up, it will create a default network called… bridge. 🤔 It should start automatically, without any configuration required by you.

From that point onwards, all containers are added into to the bridge network, unless you say otherwise.


In a bridge network, each container is assigned its own IP address. So containers can communicate with each other by IP.


How to use the default bridge network


Check that the bridge network is running: You can check it’s running by typing docker network ls. This should show the bridge network in the list.


docker network ls

NETWORK ID     NAME      DRIVER    SCOPE

acce5c7fd02b   bridge    bridge    local

a6998b3cf420   host      host      local

d7f563b21fc6   none      null      local



Start your containers: Start your containers as normal, with docker run. When you start each container, Docker will add it to the bridge network.

(If you prefer, you can be explicit about the network connection by adding --net=bridge to the docker run command.)



Address another container by its IP address: Now one container can talk to another, by using its IP address.



Below are some useful commands on this


docker inspect <container_id> | grep IPV4Address

            "IPAddress": "172.17.0.2",



Here is an example pf nginx container. Then I’ll start a busybox container alongside nginx, and try to make a request to Nginx with wget:


# Start an nginx container, give it the name 'mynginx' and run in the background

$ docker run --rm --name mynginx --detach nginx


# Get the IP address of the container

$ docker inspect mynginx | grep IPAddress

            "IPAddress": "172.17.0.2",


# Or, if you have 'jq' installed - here's a funky way to get the IP address

$ sudo docker inspect mynginx | jq '.[].NetworkSettings.Networks.bridge.IPAddress'

"172.17.0.2"


# Run busybox (a utility container). It will join the bridge network

$ docker run -it busybox sh


# Fetch the nginx homepage by using the container's IP address

busybox$ wget -q -O - 172.17.0.2:80

<!DOCTYPE html>

<html>

<head>

<title>Welcome to nginx!</title>

<style>



To see if the container is in the bridge network, the command is below 


sudo docker inspect bridge: 


This will have section like this below in the response. However, the application that was started from the docker-compose, running this command showed nothing in the container dictionary. May be that the container networking in docker-compose is different. 


 "Containers": {

        "1cdc34001e9f5b109836d...": {

            "Name": "vibrant_tesla",   # This is my busybox container

            "EndpointID": "6d51e27f9277bf2...",

            "MacAddress": "02:42:ac:11:00:03",

            "IPv4Address": "172.17.0.3/16",

            "IPv6Address": ""

        },

        "dbb6b814d0f11bfcad11e...": {

            "Name": "mynginx",         # This is my nginx container

            "EndpointID": "aa65052c8c4e26fd...",

            "MacAddress": "02:42:ac:11:00:02",

            "IPv4Address": "172.17.0.2/16",

            "IPv6Address": ""

        }

    },



One point to note is, in the default bridge scenario, each container can see each other. So a more sensible option will be user defined network. 


References:

https://www.tutorialworks.com/container-networking/


No comments:

Post a Comment