Websocket (ws4py in Python 3.5) not working in Docker container

I have a simple web application that uses CherryPy for a RESTful backend and ws4py for websockets.

1) Javascript client sends a POST to Python backend
2) Python replies with a unique id
3) Javascript connects to the websocket and sends the unique id
4) Python associates the websocket client connection to the unique id

Python websocket code:

  • DB, user not created using postgres docker-compose
  • docker-compose swarm: force containers to run on specific hosts
  • Saving docker credentials in docker config
  • Building in docker and deploying in ubuntu [closed]
  • docker-machine ls shows state timeout
  • Docker build ADD vs RUN curl
  • class WebSocketHandler(WebSocket):
    def __init__(self, *args, **kw):
        WebSocket.__init__(self, *args, **kw)
        print('Connected to websocket server!')
        SUBSCRIBERS.add(self)
    
    def received_message(self, message):
        print('Websocket identified itself?')
        SUBSCRIBERS_WITH_ID[message.data] = self
    

    Python CherryPy code:

    cherrypy.config.update({'server.socket_host': 0.0.0.0,
                            'server.socket_port': 8080})
    
    cherrypy.tools.CORS = cherrypy.Tool('before_handler', CORS)
    
    WebSocketPlugin(cherrypy.engine).subscribe()
    cherrypy.tools.websocket = WebSocketTool()
    
    cherrypy.tree.mount(
        DummyAPI(), '/api/dummy', config={
            '/': {
                'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
                'tools.CORS.on': True
            }
        }
    )
    
    cherrypy.tree.mount(
        WebSocketAPI(), '/ws', config={
            '/': {
                'tools.websocket.on': True,
                'tools.websocket.handler_cls': WebSocketHandler
            }
        }
    )
    
    cherrypy.engine.start()
    cherrypy.engine.block()
    

    Javascript code:

    POST to API:

    var req = new XMLHttpRequest();
    req.onload = function (e) {
        console.log('Response code: ' + req.responseText);
        result_id = req.responseText;
        websocketConnect();
    };
    req.open('POST', api_url);
    req.send();
    

    Websocket section:

    function websocketConnect() {
    websocket = new WebSocket(websocket_url);
    websocket.onopen = function (evt) { 
          console.log("Connected to WebSocket server.");
          websocket.send(result_id)};
    

    This works fine on my machine and deployed on Amazon EC2. However, when I try to deploy it in a Docker container, the websockets don’t work.

    Here is my Dockerfile:

    FROM python
    MAINTAINER xxx
    
    RUN pip3.5 install cherrypy ws4py
    RUN mkdir /var/www
    
    COPY python /var/www/python
    
    EXPOSE 8080
    
    CMD ["/usr/local/bin/python3.5", "/var/www/python/simplews.py"]
    

    Output when I run from Docker:

    sudo docker run  -v /tmp/dockertmp/:/tmp/ -p 8080:8080 -i 563a51d13f59
    [23/Oct/2015:10:09:00] ENGINE Bus STARTING
    [23/Oct/2015:10:09:00] ENGINE Starting WebSocket processing
    [23/Oct/2015:10:09:00] ENGINE Started monitor thread '_TimeoutMonitor'.
    [23/Oct/2015:10:09:00] ENGINE Started monitor thread 'Autoreloader'.
    [23/Oct/2015:10:09:01] ENGINE Serving on http://0.0.0.0:8080
    [23/Oct/2015:10:09:01] ENGINE Bus STARTED
    172.17.42.1 - - [23/Oct/2015:10:09:08] "POST ..."
    Connected to websocket server!
    

    It never reaches the stage where the Javascript file is able to send data through the websocket. Chrome debug shows the WS state as “Pending”.

    However, when I exit the CherryPy application in Docker, the websocket message comes through:

    enter code here
    sudo docker run  -v /tmp/dockertmp/:/tmp/ -p 8080:8080 -i 563a51d13f59
    [23/Oct/2015:10:15:30] ENGINE Bus STARTING
    [23/Oct/2015:10:15:30] ENGINE Starting WebSocket processing
    [23/Oct/2015:10:15:30] ENGINE Started monitor thread '_TimeoutMonitor'.
    [23/Oct/2015:10:15:30] ENGINE Started monitor thread 'Autoreloader'.
    [23/Oct/2015:10:15:30] ENGINE Serving on http://0.0.0.0:8080
    [23/Oct/2015:10:15:30] ENGINE Bus STARTED
    172.17.42.1 - - [23/Oct/2015:10:15:33] "POST ..."
    Connected to websocket server!
    ^C[23/Oct/2015:10:15:35] ENGINE Keyboard Interrupt: shutting down bus
    [23/Oct/2015:10:15:35] ENGINE Bus STOPPING
    [23/Oct/2015:10:15:40] ENGINE HTTP Server     cherrypy._cpwsgi_server.CPWSGIServer(('0.0.0.0', 8080)) shut down
    [23/Oct/2015:10:15:40] ENGINE Stopped thread '_TimeoutMonitor'.
    [23/Oct/2015:10:15:40] ENGINE Terminating WebSocket processing
    [23/Oct/2015:10:15:40] ENGINE Stopped thread 'Autoreloader'.
    [23/Oct/2015:10:15:40] ENGINE Bus STOPPED
    [23/Oct/2015:10:15:40] ENGINE Bus EXITING
    [23/Oct/2015:10:15:40] ENGINE Bus EXITED
    [23/Oct/2015:10:15:40] ENGINE Waiting for child threads to terminate...
    Websocket identified itself?
    

    Output when I run it without Docker:

    python3.5 python/simplews.py 
    [23/Oct/2015:06:09:45] ENGINE Bus STARTING
    [23/Oct/2015:06:09:45] ENGINE Starting WebSocket processing
    [23/Oct/2015:06:09:45] ENGINE Started monitor thread '_TimeoutMonitor'.
    [23/Oct/2015:06:09:45] ENGINE Started monitor thread 'Autoreloader'.
    [23/Oct/2015:06:09:45] ENGINE Serving on http://0.0.0.0:8080
    [23/Oct/2015:06:09:45] ENGINE Bus STARTED
    127.0.0.1 - - [23/Oct/2015:06:09:48] "POST ..."
    Connected to websocket server!
    Websocket identified itself?
    

    In the non-Docker case the websocket identifies itself immediately. I can’t figure this out. Is the websocket receiver thread stuck somehow in Docker?

    The suspicious part from the Docker logs is when the application exits, the websocket received message finally arrives:

    [23/Oct/2015:10:15:40] ENGINE Waiting for child threads to terminate...
    Websocket identified itself?
    

  • Access host XServer from Docker container
  • run django in docker container
  • Different images in containers
  • How to install nano on boot2docker
  • How to mimic a Docker registry down situation
  • Docker EXPOSE vs command line -p option (boot2docker)
  • One Solution collect form web for “Websocket (ws4py in Python 3.5) not working in Docker container”

    Replacing the Python multiprocessing module with threading.Thread fixed the problem. I was using multiprocessing in the POST method handler.

    Here’s the commit with the fix on the actual project:

    https://github.com/sevagh/youtube-audio-dl/commit/9e23ae174f8791206b934608a1d4d702b411d18e

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