How to setup flask-socketio in a docker container?

纵饮孤独 提交于 2021-02-07 19:41:30

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!