DEV Community

Cover image for How messages get exchanged between Docker containers
Jeetendra
Jeetendra

Posted on • Updated on • Originally published at w3school.info

How messages get exchanged between Docker containers

Now-a-days Since almost all applications employ containers, it goes without saying that they will need to communicate with one another. In this article, we will cover how messages may be easily sent and received between containers.

I’m assuming that your environment already has Docker installed. Next, we’ll build two apps with flask and node js and attempt to communicate between them.

Let’s start with a Python app that uses Flask.
Create a folder called “ping-app” and create app.py file, place the following code in it.

from flask import Flask
from redis import Redis

app = Flask(__name__)
redis = Redis(host='redis', port=6379)

@app.route('/')
def home():
    redis.incr('pageviews')
    return 'This app has been viewed %s time(s).' % redis.get('pageviews')

@app.route('/get-redis-count')
def count():
    return redis.get('pageviews')


if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)
Enter fullscreen mode Exit fullscreen mode

We can see from the code above that Redis is being used as a key-value pair database. and on the root route, we are returning a message with the count to print on the screen while also increasing the number of pageviews in redis by 1.

Since this application uses two packages, let’s make a requirements.txt file and include the following dependencies:

flask
redis
Enter fullscreen mode Exit fullscreen mode

Now Create a file called Dockerfile and add the following code to begin dockerizing this application:

FROM python:3.7
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD python app.py
Enter fullscreen mode Exit fullscreen mode

For the next step, we will need a docker-compose file with the following code in order to properly execute this application: Create a docker-compose.yaml file and add the following code:

version: "3.9"
services:
    web:
        build:
          context: .
          dockerfile: Dockerfile
        ports:
            - "5000:5000"
        volumes:
            - .:/code
        depends_on:
            - redis
    redis:
        image: redis
Enter fullscreen mode Exit fullscreen mode

In this code we can see that we have 2 services, 1 is web which is basically using our docker file to run our already created flask app and another service is redis, which basically runs on 6379 port by default. So lets run the app now using following command in your workspace terminal.

docker-compose up

Your redis and web services will both become operational as a result.
Using http://localhost:5000, let’s open your flask application now on browser. and whoohoo, the results are displayed as shown.

Image description

Now Reload this app in your browser now a number of times to observe if the count increases each time the page loads.

Also Check out the other endpoint in the same app, http://localhost:5000/get-redis-count, which simply returns the screen count number value.

So far, everything has been rather simple. Let’s assume that you have another Node.js application that wishes to receive the pageview count.

let’s make that Node App as well utilising the techniques below:
Make a new folder called pong-app as a sibling to ping-app, and then place a package.json file containing the following information:

{
    "name": "pong-app",
    "version": "1.0.0",
    "description": "",
    "author": "Jeetendra Singh <jeetendra.apps@gmail.com>",
    "main": "app.js",
    "scripts": {
        "start": "node app.js"
    },
    "dependencies": {
        "axios": "^1.1.2",
        "express": "^4.16.1"
    }
}
Enter fullscreen mode Exit fullscreen mode

After this lets create app.js file parallel to package.json file with following code:

const express = require('express');
const axios = require('axios');
// Constants
const PORT = 8000;
const HOST = '0.0.0.0';

// App
const app = express();
app.get('/', (req, res) => {
  res.send('Hello Node');
});

app.listen(PORT, HOST, () => {
  console.log(`Running on http://${HOST}:${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

The code above is simply the beginning of a small express application. Hello Node, let’s first dockerize this application. thus make a Dockerfile file with the following information in it.

FROM node:16 
WORKDIR /usr/app
COPY package*.json ./
RUN npm install
COPY . .
CMD node app.js
Enter fullscreen mode Exit fullscreen mode

Lets create a docker-compose.yaml file for this app with following information:

version: "3.9"
services:
    server:
        build:
          context: .
          dockerfile: Dockerfile
        ports:
            - "8000:8000"
        volumes:
            - .:/usr/app
            - /usr/app/node_modules
Enter fullscreen mode Exit fullscreen mode

You are now prepared for this app, docker-compose up can be used to start an application, which will then run on http://localhost:8000. and on the root route, it will output Hello Node.

Now that both apps are operating in separate containers, the easiest approach to display the number of pageviews for the Python app in the node js app is to access the /get-redis-count API on the existing Flask app.
Let’s create a function in Node.js to retrieve the pageview count from a Flask application using the existing Flask api.

app.get("/get-data-from-ping-app",async (req,res)=>{ 
  //call flask based api
  try{
    const response= await axios.get('http://web:5000/get-redis-count')
    console.log('redis count in flask app is ',response.data)
    res.json({count:response.data})
  }catch(err){
    const error='Node App is not able to connect with flask app';
    console.log(error)
    res.send(error)
  }
})
Enter fullscreen mode Exit fullscreen mode

We are attempting to call the departing endpoint /get-redis-count running inside the Flask app in the aforementioned code.

Also, if you’ve observed, we used web:5000 instead of localhost:5000 when creating the url for the flask app (http://web:5000/get-redis-count). Therefore, in order to access resources within containers using the http protocol, we must utilise the container service name defined in the compose file. The service name for this Flask app is web, which is why the url is web:5000.

Now let’s restart our node app and test whether we still obtain the desired results by accessing http://localhost:8000/get-data-from-ping-app.

Currently, the output message will read: Node App is unable to connect with Flask App.

But why? Because there is no networking between the two apps, which are running independently. Therefore, we need to make a few changes to both apps in order to create a network between them.

Just before services, add the network my-local-net with a driver bridge to the docker-compose.yaml file of both apps(ping & pong).

networks:
 my-local-net:
  name: my_local_net
  driver: bridge
Enter fullscreen mode Exit fullscreen mode

Add the following code to the services section of both docker-compose files to connect the created network to each service.

networks:
       - my-local-net
Enter fullscreen mode Exit fullscreen mode

Let’s take a last glance at the docker-compose files:

Ping App’s docker-compose.yaml file(Flask based app)

version: "3.9"
networks:
 my-local-net:
  name: my_local_net
  driver: bridge
services:
    web:
        build:
          context: .
          dockerfile: Dockerfile
        ports:
            - "5000:5000"
        networks:
            - my-local-net
        volumes:
            - .:/code
        depends_on:
            - redis
    redis:
        image: redis
        networks:
            - my-local-net
Enter fullscreen mode Exit fullscreen mode

Pong App’s docker-compose.yaml file(Node.js based app)

version: "3.9"
networks:
 my-local-net:
  name: my_local_net
  driver: bridge
services:
    server:
        build:
          context: .
          dockerfile: Dockerfile
        ports:
            - "8000:8000"
        networks:
            - my-local-net
        volumes:
            - .:/usr/app
            - /usr/app/node_modules
Enter fullscreen mode Exit fullscreen mode

Restart both apps now, then try to access the following URL to view pageviews for the flask app in Node.js:

http://localhost:8000/get-data-from-ping-app

It will respond with something like

{“count”:x}

Note: that x is merely a stand-in for count, which will be an integer value.

Finally, since they are all declared under the same network, separate apps running in Docker containers can connect with one another using Network Driver Bridge.

you can get the complete source code from our download center. Additionally, if you have any questions, please comment below or email me on jeetendra.apps@gmail.com

Top comments (0)