[英]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
?
我已经复制了您的示例并且它有效,即使它似乎在一段时间后超时。
# 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.
显示的日志来自容器内部。 我刚刚在服务器代码中添加了一个日志来显示收到的消息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}
如果我尝试让容器运行并再次启动客户端,我会观察到连接被拒绝。 此时我想问题似乎与您使用 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.