Connect to socket container from javascript

support
javascript
docker

#1

So I have a multicontainer app in which one of the containers is a node socket-server to be used from the client side of a web server in another container, using socket_io_2_0_3 library.

Usually the connection in javascript should be as simple as:

  1. Importing the lib
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>

  2. connect to it:
    var socket = io('http://localhost:3334');

in this example case, the socket-server is running in local on port 3334.

In my real scenario I’m running the socket server on a container, and the webserver in another, with a compose file looking something like:

version: '2'
services:
  nginx:
    build: ./nginx
    depends_on:
      - web
    ports:
      - "80:80"
  ss1:
    build: ./socket-server
    command: bash /tmp/start.sh
    ports:
      - "3334:3334"
  web:
    build: ./first-pitch
    command: bash /tmp/start.sh
    depends_on:
      - ss1
    ports:
      - "3000:3000"

one might think it should be called something like:

var socket = io('http://ss1:3334');

But, I get an error when reaching through the public URL.

How am I supposed to link to a container from the clients JS side?


#4

Hi @felixbanguera !

I suspect it’s missing an expose statement that would expose said port (3334) to the outside world, you can see an example of that in the docker-compose file in: https://github.com/resin-io-projects/multicontainer-getting-started

Let us know if that helped!


#5

Hi @chrischabot ,

Thanks for the response.

I tried what you just mentioned and it’s not working, I get a Failed in: http://ss2:3334/socket.io/?EIO=3&transport=polling&t=MDf4TfG

I talked to one of the guys of chat support and they say the problem is I’m trying to reach a container from a browser, which makes sense. However, I’m wondering if there is a way to access that server in the container, from a browser using the same wifi network.

Thanks in advance.


#6

Ah yes that does add an additional layer of considerations.

Is the computer running the webbrowser on the same local network? And if so, is “ss2” in your URL resolving to the local device address? If so that should just work if you have an expose: 3334 in the ss1 section of your docker compose file.

If they’re on different networks, or if you’re trying to connect over the internet to it, you’d have to use the PUBLIC DEVICE URL in the dashboard to be able to connect to it.

In the second case it would only connect to port 80 on your device, however using the haproxy that’s included in the sample that i linked you can route the traffic to the correct container using this configuration:

Notice how the default traffic goes to the backend_static_server while anything that looks like a websocket gets routed to the backend_data – a similar approach could work here too


#7

The second option seems to be the solution for this case, however I’ve never used haproxy, I’ve always used nginx.

Any ideas how the nginx.conf file should look like in this case??

Any help would be appreciated.

Thks


#8

I’m not entirely sure as I haven’t set that up using ngix, but I hope https://www.nginx.com/blog/websocket-nginx/ would be useful


#9

So, what finally worked for me was to set the upstream in nginx.conf and redirect all socket.io calls to that upstream, the final file looks like:

events {
  worker_connections  1024;
}

http {
  upstream web {
    server web:3000;
  }

  upstream socketserver {
    server ss2:3334;
  }

  include       mime.types;
  default_type  application/octet-stream;

  sendfile        on;

  keepalive_timeout  65;

  server {
    listen       80;

    location / {
      proxy_pass http://web;
    }

    location /socket.io {
      proxy_pass http://socketserver;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
      root   html;
    }
  }

  include servers/*;
}

#11

Thanks for sharing @felixbanguera2h! Great to hear you got it working