Fly not letting Socketio work?

I have a flask project that utilizes Flask-Socketio, The project works just fine locally, but it breaks when I deploy it on Fly.io, I know I am probably overlooking something here but I honestly spent hours on this and developed a bit of a tunnel vision, I hope someone can give me a helping hand here.

Dockerfile:

FROM python:3.11-bullseye

ENV PIP_DISABLE_PIP_VERSION_CHECK 1
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

WORKDIR /flask-app

COPY ./requirements.txt .

RUN pip install --only-binary :all: greenlet
RUN pip install --only-binary :all: Flask-SQLAlchemy
RUN pip install -r requirements.txt

COPY . .

EXPOSE 5000

CMD ["python", "app.py"]

fly.toml:

# fly.toml app configuration file generated for appname on 2023-10-24T18:03:37+03:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#

app = "appname"
primary_region = "cdg"

[build]

[http_service]
  internal_port = 5000
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 0
  processes = ["app"]

app.py:

#!/bin/env python
from app import create_app, socketio

app = create_app(debug=True)

if __name__ == '__main__':
    socketio.run(app, host='0.0.0.0' , port=5000 )

mockup.html:

<html>
    <head>
        <title>Flask-SocketIO-Chat: {{ room }}</title>
        <script type="text/javascript" src="//code.jquery.com/jquery-1.4.2.min.js"></script>
        <script type="text/javascript" src="//cdn.socket.io/4.4.1/socket.io.min.js"></script>
        <script type="text/javascript" charset="utf-8">
            var socket;
            $(document).ready(function(){
                console.log(location.port)
                socket = io.connect('wss://' + document.domain + ':' + location.port + '/chat');
                socket.on('connect', function() {
                    socket.emit('joined', {});
                });
                socket.on('status', function(data) {
                    $('#chat').val($('#chat').val() + '<' + data.msg + '>\n');
                    $('#chat').scrollTop($('#chat')[0].scrollHeight);
                });
                socket.on('message', function(data) {
                    $('#chat').val($('#chat').val() + data.msg + '\n');
                    $('#chat').scrollTop($('#chat')[0].scrollHeight);
                });
                $('#text').keypress(function(e) {
                    var code = e.keyCode || e.which;
                    if (code == 13) {
                        text = $('#text').val();
                        $('#text').val('');
                        socket.emit('text', {msg: text});
                    }
                });
            });
            function leave_room() {
                socket.emit('left', {}, function() {
                    socket.disconnect();

                    // go back to the login page
                    window.location.href = "{{ url_for('main.index') }}";
                });
            }
        </script>
    </head>
    <body>
        <h1>Flask-SocketIO-Chat: {{ room }}</h1>
        <textarea id="chat" cols="80" rows="20"></textarea><br><br>
        <input id="text" size="80" placeholder="Enter your message here"><br><br>
        <a href="#" onclick="leave_room();">Leave this room</a>
    </body>
</html>

Browser console:

POST
https://appname.fly.dev/socket.io/?EIO=4&transport=polling&t=OjYF7-k&sid=BEtZLFq16UD-8e5kAAAA
[HTTP/2 400  69ms]

GET
wss://appname.fly.dev/socket.io/?EIO=4&transport=websocket&sid=BEtZLFq16UD-8e5kAAAA

Firefox can’t establish a connection to the server at wss://appname.fly.dev/socket.io/?EIO=4&transport=websocket&sid=BEtZLFq16UD-8e5kAAAA. websocket.js:54:26
The connection to wss://appname.fly.dev/socket.io/?EIO=4&transport=websocket&sid=BEtZLFq16UD-8e5kAAAA was interrupted while the page was loading.

Fly.io monitoring console:

2023-10-24T15:10:15.037 app[3287335a195618] cdg [info] 41.34.69.24,66.241.124.11,172.16.154.90 - - [24/Oct/2023 15:10:15] "GET /socket.io/?EIO=4&transport=polling&t=OjYF8Kk&sid=IXEClNUPlzR27_YCAAAA HTTP/1.1" 200 195 0.000131

2023-10-24T15:10:15.318 app[3287335a195618] cdg [info] (310) accepted ('172.16.154.90', 46270)

2023-10-24T15:10:15.320 app[3287335a195618] cdg [info] 41.34.69.24,66.241.124.11,172.16.154.90 - - [24/Oct/2023 15:10:15] "POST /socket.io/?EIO=4&transport=polling&t=OjYF8PA&sid=IXEClNUPlzR27_YCAAAA HTTP/1.1" 200 201 0.001092

2023-10-24T15:10:15.323 app[d891241fe51d18] cdg [info] (310) accepted ('172.16.12.146', 44206)

2023-10-24T15:10:15.323 app[d891241fe51d18] cdg [info] Invalid session IXEClNUPlzR27_YCAAAA (further occurrences of this error will be logged with level INFO)

Hi - This is a complete shot in the dark, but: by default the Fly.io deployment will create two machines, and the fact that in your log it complains about a mismatched session ID and there are two distinct logged session IDs for two Machines, makes me think the initial request that creates the session hits the first machine and the second request gets to the second machine, which knows nothing about the session and then barfs.

If so, you can probably test this theory by destroying one of your two machines (fly machine destroy) and seeing if things behave properly with only one machine handling all connections.

If that’s the case, then you need to look at how to deploy flask-socketio in a multi-worker, behind-a-balancing-proxy setup (which by the way is exactly what the Fly.io deployment with two machines is) - this is well-explained in the flask-socketio page here.

Cheers,

  • Daniel

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.