Node.js tcp sockets + linked Docker containers

I have two node apps in two Docker containers.
1. Main web app
2. A profile service using sockets over tcp

I link the Profile Service container to the Main Web App container using this option when running the Docker container

  • Kubernetes: Docker pod starting fails except one
  • Docker Image Requirements for a GitLab-CI Runner
  • jenkins docker plugin job “Permission denied” error
  • How to run docker-compose in Azure Container Service and deploy to agent rather than master?
  • connecting to local mongodb from docker container
  • Easy way to give docker container access to my local domains (.local, .dev)
  • --link srv-profile:srv_profile
    

    And it seems to be linking it just fine. I can say this because I am able to see the following in my Main web app container:

    root@8d6247a82b6d:/app# echo $SRV_PROFILE_PORT
    tcp://10.1.0.8:4000
    root@8d6247a82b6d:/app#
    

    The problem I am facing is that my Main web app container is not able to establish a connection with my Profile Service container. Here is the output when I start my main web app:

    root@8d6247a82b6d:/app# nodemon server.js
    3 Nov 01:22:43 - [nodemon] v1.2.1
    3 Nov 01:22:43 - [nodemon] to restart at any time, enter `rs`
    3 Nov 01:22:43 - [nodemon] watching: *.*
    3 Nov 01:22:43 - [nodemon] starting `node server.js`
    web.main listening on port 4000...
    Connection closed
    

    I would really appreciate if you can please point me into the right direction.

    Here is my code for both Profile Service and Main Web App

    srv-profile\server.js

    var net = require('net');
    
    var HOST = '127.0.0.1';
    var PORT = 4000;
    
    // Create a server instance, and chain the listen function to it
    // The function passed to net.createServer() becomes the event handler for the 'connection' event
    // The sock object the callback function receives UNIQUE for each connection
    net.createServer(function(sock) {
    
        // We have a connection - a socket object is assigned to the connection automatically
        console.log('CONNECTED: ' + sock.remoteAddress +':'+ sock.remotePort);
    
        // Add a 'data' event handler to this instance of socket
        sock.on('data', function(data) {
    
            console.log('DATA ' + sock.remoteAddress + ':');
            console.log(data);
            console.log();
    
            // Write the data back to the socket, the client will receive it as data from the server
            sock.write('You said "' + data + '"');
        });
    
        // Add a 'close' event handler to this instance of socket
        sock.on('close', function(data) {
            console.log('CLOSED: ' + sock.remoteAddress +' '+ sock.remotePort);
        });
    
    }).listen(PORT, HOST);
    
    console.log('Server listening on ' + HOST +':'+ PORT);
    

    web-main\server.js

    var env = process.env.NODE_ENV = process.env.NODE_ENV || 'development';
    
    var express             = require('express'),
        logger              = require('morgan'),
        profileManager      = require('./lib/profile-manager');
    
    var app = express();
    
    app.use(logger('dev'));
    
    app.listen(4000, function() {
      console.log('web.main listening on port 4000...');
    
      profileManager.connect();
      profileManager.disconnect();
    });
    

    web-main\lib\profile-manager.js

    var net = require('net');
    
    var client = new net.Socket();
    
    var _connect = function() {
        client.connect(process.env.SRV_PROFILE_PORT, function() {
            console.log('CONNECTED TO: ' + process.env.SRV_PROFILE);
    
            // Write a message to the socket as soon as the client is connected, the server will receive it as message from the client
            client.write({
                action: 'doSomething',
                data: '1234',
                source: 'web-main'
            });
        });
    
        // Add a 'data' event handler for the client socket
        // data is what the server sent to this socket
        client.on('data', function(data) {
            console.log('DATA: ' + data);
        });
    
        // Add a 'close' event handler for the client socket
        client.on('close', function() {
            console.log('Connection closed');
        });
    };
    
    var _disconnect = function() {
        // Close the client socket completely
        client.destroy();
    };
    
    module.exports = {
      connect: _connect,
      disconnect: _disconnect
    };
    

  • Possible to set --insecure-registry property in Docker on AWS Elastic Beanstalk
  • Docker: combine docker layers into image
  • How do I attach VisualVM to a simple Java process running in a Docker container
  • MySQL docker image not working as Local MySQL server
  • How to deploy Kubernetes with Docker locally?
  • Dockerfile COPY {source-…}
  • 2 Solutions collect form web for “Node.js tcp sockets + linked Docker containers”

    If I’m reading your code correctly, you’re profile service is only listening on 127.0.0.1. However, the web app is calling from another IP Address. Different containers have different IPs. So the profile service is denying the incoming connection because it is coming in to an invalid IP.

    Have you tried to run it locally, w/o docker? I made this an exercise for myself and found multiple issues:

    • As mentioned before, server should bind to 0.0.0.0 to listen on all interfaces
    • Docker file for server must EXPOSE 4000 (which it seemingly does in your example, since the link works)
    • Socket.connect() does not accept the docker-style url (i.e. ‘tcp://172.17.0.12:4000’), it must be an options object like {host: 'bla', port: '1337'} – use Node’s url module to parse the variable provided by docker.
    • As far as I can see, your client immediately disconnects right after it initiates the connection (the disconnect() call in profile-manager.js)
    • You can’t just write an object to the socket. Sensible choice for encoding would be JSON.stringify()

    Moreover, since data received via the socket is a Buffer, using data.toString('utf-8') should result in human-readable output.

    Working example can be found on https://github.com/joerx/node-docker-tcp-sockets

    Docker will be the best open platform for developers and sysadmins to build, ship, and run distributed applications.