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

  • How to change Ruby and Rails version for the Rails base Docker image?
  • Cannot change permissions of the '/' directory in Docker
  • Is it possible to use Docker 17.03 secrets in Drupal 8?
  • I am not able to configure Docker VM for Lightbend ConductR. Sandbox init is throwing FileNotFoundError
  • Make Docker image error
  • Shared Volume in Docker through Vagrant
  • --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
    };
    

  • multiple django requirements with docker
  • Unable to push docker image on local private registry
  • Paperclip on docker doesn't upload image?
  • Docker: Issues establishing PostgreSQL connection in Rails application
  • Node http-proxy in Docker container
  • Understanding “VOLUME” instruction in DockerFile
  • 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.