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:

  • Communication with Spark using Spark JobServer in docker
  • How to switch between active docker machine on window
  • Schedule a container with docker swarm using gpu memory as a constraint
  • rsync files from inside a docker container?
  • `docker service update` from remote server with cert
  • Gcloud push error : ERROR: gcloud crashed (ValueError): No JSON object could be decoded
  • 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?
    

  • Docker: mounting volumes from other docker service (not container)
  • Octohost with knife solo on bare metal? (UserError: Vagrant not installed)
  • AWS EB should create new instance once my docker reached its maximum memory limit
  • Is there a way for docker-compose to save and open a docker image?
  • What is the tool to deploy dockerized apps?
  • Docker Swarm discovery is still relevant?
  • 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.