8

I'm deploying a flask server to a Digital Ocean droplet.

from flask import Flask

app = Flask(__name__)

@app.route("/a/<string:b>")
def deploy(b):
    return "Response"

Using the following command:

FLASK_APP=server.py python -m flask run --host=0.0.0.0 --port=5555

When I deploy the application locally, I can receive response by doing

curl -XGET localhost:5555/a/random

When deploying on the droplet, it works internally, but when calling the droplet externally (despite having exposed port 5555 on TCP) it does not connect.

What could have changed? I'm also deploying a flask graphql server on the same droplet via docker which works perfectly fine.

Peteris
  • 3,548
  • 4
  • 28
  • 44
  • What command did you use to expose the 5555/tcp port? – Cole Jul 05 '18 at 22:03
  • What's the output of `netstat -nltp` ? Do you have the DigitalOcean firewall enabled or run e.g. ufw on the droplet? If yes, what's the output of `ufw status` ? – Oliver Jul 06 '18 at 00:03
  • I’ve exposed the port via the web interface. This same approach worked for the flask_graphql server on a different port. I will run the commands you suggest and report back later! – Peteris Jul 06 '18 at 08:15
  • This is the output from netstat: Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:5555 0.0.0.0:* LISTEN 3971/python3 – Peteris Jul 07 '18 at 07:09
  • @Oliver - see above for netstat output – Peteris Jul 07 '18 at 07:09
  • You mentioned the other deploy you did in the same droplet was using docker. Is this deploy also using docker? If so, did you remember to map the port in the container? – Fernando Cezar Jul 20 '18 at 13:20
  • It's not using docker, it's directly exposed on localhost. – Peteris Jul 23 '18 at 10:06

2 Answers2

5

This is possible a common issue when uses VPS. People like me may often forget to setup firewall(s) if the codes are correct.

You mentioned that it works locally but not externally. I guess it should be.

Digital Ocean level:

  • Add inbound TCP port 5555 in droplet firewall setting

System level

  • iptables: e.g. iptables -A INPUT -p tcp -dport 5555 -j ACCEPT
  • firewalld: e.g. firewall-cmd --permanent --zone=public --add-port=5555/tcp

Or you may disable OS firewalls by systemctl stop [service-name] or service [service-name] stop. You may google the commands.

Samuel Chen
  • 2,124
  • 14
  • 9
  • I have set up the firewalls in Digital Ocean. When using Docker, there was no need to enable additional firewalls on the machine, can you confirm this is needed in addition to the docker set-up? – Peteris Jul 25 '18 at 08:37
  • Hmmm, I am not sure whether docker need to setup firewalls on host machine. I remember that docker will create an bridge adapter for connections. But I did not dig into it to see if it need firewall setting. Besides, "docker start" need "-p 5555:5555" argument to map container port to host port. – Samuel Chen Jul 26 '18 at 04:50
  • I checked this articlle [ https://docs.docker.com/network/iptables/ ]. It looks docker will automatically add rules to iptables so that user no need to add rules by self. And for other OS level firewalls such as firewalld and etc, I am not sure if docker can automatically setup the rules. But on Digital Ocean level, I guess you still need to open the port so that the traffic may like this : "container port 5555" -> "host port 5555" -> "digital ocean firewall 5555" – Samuel Chen Jul 26 '18 at 04:55
  • fix an issue. I mentioned "docker start", it should be "docker run" – Samuel Chen Jul 26 '18 at 04:59
  • From this "I'm also deploying a flask graphql server on the same droplet via docker which works perfectly fine.", I think that you opened the port on Digital Ocean but not in system firewall(s). As docker will automatically add rules to iptables, It can works. Without docker, the port is not opened. We can have a try to simply disable system firewalls to check if it works. – Samuel Chen Jul 26 '18 at 05:04
2

Flask accepts connections from localhost by default.

In order to make your Flask app publicly available, you have to bind it to 0.0.0.0 address by adding --host=0.0.0.0 parameter.

Externally Visible Server

If you run the server you will notice that the server is only accessible from your own computer, not from any other in the network. This is the default because in debugging mode a user of the application can execute arbitrary Python code on your computer.

If you have the debugger disabled or trust the users on your network, you can make the server publicly available simply by adding --host=0.0.0.0 to the command line:

flask run --host=0.0.0.0 This tells your operating system to listen on all public IPs.

Community
  • 1
  • 1
ramazan polat
  • 7,111
  • 1
  • 48
  • 76