如何让 SocketIO 在本地工作时在 Docker 中工作?

How can I get SocketIO to work in Docker when it's working locally?

当我 运行 flask run -p 8000 时,我的 Flask 应用程序在本地运行,但是当我尝试 运行 在 Docker 中执行此操作时,我的 SocketIO 事件似乎没有通过从服务器到客户端。

这是一个示例应用程序来说明我的意思:

Flask 应用程序:

import flask
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
import requests
import logging
import time
import os

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, logger=False, engineio_logger=False)

# Flask App

@app.route('/')
def index():
    return render_template('index.html')

@socketio.on('hello')
def connected(message):
    data = message
    print('Message received from browser:', data)
    
    # Thanks I got your message
    emit('reply', {'data': 'Hello browser. I received your message.'})

if __name__ == '__main__':
    app.run(debug=True,host='0.0.0.0',port=int(os.environ.get('PORT', 8000)))

Docker文件:

FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7
RUN apk add g++
RUN apk add linux-headers
RUN apk add libc-dev
RUN apk add musl-dev
COPY requirements.txt /
RUN python -m pip install --upgrade pip
RUN pip3 install numpy
RUN pip install -r /requirements.txt
COPY . /
WORKDIR /
ENV PORT 8000
RUN chmod +x ./gunicorn_starter.sh
ENTRYPOINT ["sh","./gunicorn_starter.sh"]

gunicorn_starter.sh:

#!/bin/bash
gunicorn --chdir / app:app -w 2 --threads 2 --workers 1 -b 0.0.0.0:8000

它 运行 从 Docker 开始真的很慢而且 SocketIO 事件似乎没有注册。这是我看到的错误:

[2022-01-27 20:35:31 +0000] [9] [ERROR] Error handling request /socket.io/?EIO=3&transport=websocket&sid=7862ffa61dcc4c1abbf38c368975d2b9
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/gunicorn/workers/gthread.py", line 279, in handle
    keepalive = self.handle_request(req, conn)
  File "/usr/lib/python3.6/site-packages/gunicorn/workers/gthread.py", line 336, in handle_request
    resp.close()
  File "/usr/lib/python3.6/site-packages/gunicorn/http/wsgi.py", line 409, in close
    self.send_headers()
  File "/usr/lib/python3.6/site-packages/gunicorn/http/wsgi.py", line 325, in send_headers
    tosend = self.default_headers()
  File "/usr/lib/python3.6/site-packages/gunicorn/http/wsgi.py", line 306, in default_headers
    elif self.should_close():
  File "/usr/lib/python3.6/site-packages/gunicorn/http/wsgi.py", line 229, in should_close
    if self.status_code < 200 or self.status_code in (204, 304):
AttributeError: 'Response' object has no attribute 'status_code'

我最终在我的 Dockerfile 中使用了这个命令,它成功了:

CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "1", "--worker-class", "eventlet", "app:app"]