繁体   English   中英

将外部客户端连接到 Docker websocket

[英]Connect external client to Docker websocket

我创建了一个使用socketio的 Flask python 应用程序,它在0.0.0.0:5000上运行。 当我在本地运行它时,我有一个单独的 Python 客户端,它使用socketio尝试连接到localhost:5000并将消息发送到 WebSocket 连接。 消息显示在网页等上。

问题:当我将 Flask 应用程序包装在 Docker 容器中时,我可以打开它并查看网页。 我正在使用docker run -it --rm -p 5000:5000 myapp:latest来运行这个容器。 当我尝试运行容器外的client.py以连接到运行 Flask WebSocket 连接的容器时,出现“服务器拒绝连接”错误。 我在外部客户端中使用: httP://localhost:5000尝试连接到 Docker 容器。

如何从外部 python 客户端连接到容器中的 WebSocket 服务器?

码头工人文件:

 # For more information, please refer to https://aka.ms/vscode-docker-python FROM python:3.8-slim-buster EXPOSE 5000 # Keeps Python from generating .pyc files in the container ENV PYTHONDONTWRITEBYTECODE=1 # Turns off buffering for easier container logging ENV PYTHONUNBUFFERED=1 # Install pip requirements ADD requirements.txt . RUN python -m pip install -r requirements.txt RUN apt-get update -y RUN apt-get install -y netcat WORKDIR /app ADD . /app # Switching to a non-root user, please refer to https://aka.ms/vscode-docker-python-user-rights RUN useradd appuser && chown -R appuser /app USER appuser # During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug CMD ["gunicorn", "--bind", "0.0.0.0:5000", "application:app"]

烧瓶应用:

 from flask_socketio import SocketIO, emit from flask import Flask, render_template, url_for, copy_current_request_context from random import random from time import sleep from threading import Thread, Event app = Flask(__name__) app.config['SECRET_KEY'] = 'abcd!' app.config['DEBUG'] = True #turn the flask app into a socketio app socketio = SocketIO(app, async_mode=None, logger=True, engineio_logger=True) @socketio.on('timseriespoint', namespace='/test') def to_chart_display(msg): socketio.emit('tochart', {'number': msg.get('number')}, namespace='/test') #socketio.sleep(5) @app.route('/') def index(): #only by sending this page first will the client be connected to the socketio instance return render_template('index.html') @socketio.on('connect', namespace='/test') def test_connect(): print('Client connected') @socketio.on('disconnect', namespace='/test') def test_disconnect(): print('Client disconnected') if __name__ == '__main__': socketio.run(app, host='0.0.0.0', port=5000)

客户端(容器外):

 import socketio import time import random if __name__ == '__main__': # standard Python sio = socketio.Client() sio.connect('http://0.0.0.0:5000', namespaces=['/test']) i=0 while True: i+=1 random_number = random.uniform(-100, 100) sio.emit('timseriespoint', {'number': random_number}, namespace='/test') time.sleep(1) if i > 50: break sio.disconnect()

我认为你的docker run -it --rm -p 5000:5000 myapp:latest的一般方法是可以的。

我只是想知道您的 docker 网络是如何配置的。 您是否在 docker 网络中使用网桥?

如果没有:创建一个网桥: https : //docs.docker.com/network/应该提供信息

您的应用程序是否真的在容器内部监听0.0.0.0而不是127.0.0.1

我已经复制了您的示例并且它有效,即使它似乎在一段时间后超时。

重现问题

  1. 启动服务器容器
# launching the server (named flask)
$ docker run -dit --rm -p 5000:5000 --name flask flask 

# [2020-11-06 07:55:04 +0000] [1] [INFO] Starting gunicorn 20.0.4
# [2020-11-06 07:55:04 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)
# [2020-11-06 07:55:04 +0000] [1] [INFO] Using worker: sync
# [2020-11-06 07:55:04 +0000] [7] [INFO] Booting worker with pid: 7
# Server initialized for threading.
  1. 从外部(主机)连接到它

显示的日志来自容器内部。 我刚刚在服务器代码中添加了一个日志来显示收到的消息print(f"Received message -> {msg}")

# launching the client
$ python client.py

$ docker logs -f flask  

# 0e2aceeafa664700ae2f6f9892b7ca07: Sending packet OPEN data {'sid': '0e2aceeafa664700ae2f6f9892b7ca07', 'upgrades': [], 'pingTimeout': 60000, 'pingInterval': 25000}
# 0e2aceeafa664700ae2f6f9892b7ca07: Sending packet MESSAGE data 0
# 0e2aceeafa664700ae2f6f9892b7ca07: Received packet MESSAGE data 0/test
# Client connected
# 0e2aceeafa664700ae2f6f9892b7ca07: Sending packet MESSAGE data 0/test
# 0e2aceeafa664700ae2f6f9892b7ca07: Received packet PING data None
# 0e2aceeafa664700ae2f6f9892b7ca07: Sending packet PONG data None
# 0e2aceeafa664700ae2f6f9892b7ca07: Received packet MESSAGE data 2/test,["timseriespoint",{"number":-13.160625972337428}]
# received event "timseriespoint" from 0e2aceeafa664700ae2f6f9892b7ca07 [/test]
# emitting event "tochart" to all [/test]
# 0e2aceeafa664700ae2f6f9892b7ca07: Sending packet MESSAGE data 2/test,["tochart",{"number":-13.160625972337428}]
# Received message -> {'number': -13.160625972337428}
  1. 拒绝连接

如果我尝试让容器运行并再次启动客户端,我会观察到连接被拒绝。 此时我想问题似乎与您使用 Flask-SocketIO 的框架有关,而不是与 Docker 有关。

$ python client.py

# Traceback (most recent call last):
# ...
# socketio.exceptions.ConnectionError: Connection refused by the server

调试

您可以尝试检查默认网桥以查看容器是否使用它。

$ docker network inspect bridge

# "Containers": {
#      "71451e0d82b578f63baa36b6e8fc1e33a9f4ca29f9c3460394723042fe3cf490": {
#          "Name": "flask",
#          "EndpointID": "320744772e66b28075949d81c1976a616eff278406a2027135e4542fb5f3e140",
#          "MacAddress": "02:42:ac:11:00:02",
#          "IPv4Address": "172.17.0.2/16",
#          "IPv6Address": ""
#      }
#  },
#  "Options": {
#      "com.docker.network.bridge.default_bridge": "true",
#      "com.docker.network.bridge.enable_icc": "true",
#      "com.docker.network.bridge.enable_ip_masquerade": "true",

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM