问题
Hello I'm trying to setup flask-socketio in a docker container. It seems to run but I get an error( from the browser) when I try to access localhost on port 5000 like I'm used to do with flask apps. It say's: unable to connect!
I will show you the 5 important files: Dockerfile, requirements.txt, docker-compose.yml, web_app.py and index.html
Dockerfile:
FROM python:3.6.5
WORKDIR /code
COPY * /code/
RUN pip install -r requirements.txt
requirements.txt:
Flask==1.0.2
Flask-SocketIO==3.0.1
eventlet==0.24.1
docker-compose.yml:
version: "3"
services:
web:
build: ./web
ports:
- '5000:5000'
volumes:
- './web:/code'
I use the commands docker-compose up --build
and docker-compose run web /bin/bash
to enter this container in interactive mode.
web_app.py:
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
@app.route('/')
def index():
return render_template('index.html')
@socketio.on('my event')
def log_message(message):
emit('my response', {'data': 'got it!'})
if __name__ == '__main__':
socketio.run(app)
index.html:
<!doctype html>
<html>
<head>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
<title>SocketIO</title>
</head>
<body>
<script type="text/javascript" charset="utf-8">
//Establish connection and emit a message to confirm.
var socket = io.connect('http://' + document.domain + ':' + location.port);
socket.on('connect', function() {
socket.emit('my event', {data: 'I\'m connected!'});
});
</script>
</body>
</html>
Once inside the container I simple run: python web_app.py
but nothing happens. No error and no working page.
I feel like I'm missing so steps to initialize everything correctly but I cant find out what it is. The web is full of very different examples and I'm confused. What makes it even harder is that I'm using eventlet here but not every example goes this route. Some use gevent or other things.
I would be really glad if someone gave me a little hint. Cheers
回答1:
Update2 While its true and is a better practice what I wrote below, I found out about one feature of docker-compose which would make the initial code from the question run. We need to add --service-ports or the ports won't get exposed by the run
command:
docker-compose run --service-ports web
Update: I found out that we can define the local host in the docker-compose.yaml aswell and dont have to pass it as argument in the python file.
The entrypoint for the host needs double -- like this:
- --host=0.0.0.0
The updated docker-compose file:
version: "3"
services:
web:
build: ./web
volumes:
- './application:/application'
environment:
FLASK_DEBUG: 1
FLASK_ENV: development
FLASK_APP: __init__.py
ports:
- '5000:5000'
entrypoint:
- flask
- run
- --host=0.0.0.0
Old----- :
So it turns out that the solution (I dont know how usefull it is yet) is a combination of suggested things here.
So first of all I need to set the host as argument in my python file like this:
if __name__ == '__main__':
socketio.run(app, host='0.0.0.0')
Furthermore I cant just use docker-compose run web /bin/bash
and then python web_app.py
but Instead I have to use and entrypoint in my docker-compose file for the web service like this:
entrypoint:
- python
- web_app.py
When these two things are combined I actually can see my page at port 5000 when using docker-compose up
. The web-service gets attached and runs the app. Now I only have to see how useful this is because I mount my code directory as volume so I don't have to rebuild the image all the time. I'm not sure yet if this still works as intended.
Thanks to everyone helping me out here.
Edit: So to get my desired behavior I can use the flask environment variables. I set them In the docker-compose.yml like this for my web service:
environment:
FLASK_DEBUG: 1
FLASK_ENV: development
P.s. Here is the complete docker-compose.yml to be more clear:
version: "3"
services:
web:
build: ./web
environment:
FLASK_DEBUG: 1
FLASK_ENV: development
ports:
- '5000:5000'
volumes:
- './web:/code'
entrypoint:
- python
- web_app.py
回答2:
You haven't started app in your docker container. Add two more lines to the Dockerfile:
EXPOSE 5000
ENTRYPOINT ["python", "/code/web_app.py"]
来源:https://stackoverflow.com/questions/51920267/how-to-setup-flask-socketio-in-a-docker-container