Docker container Flask Api not responding to Postman request - python

I am trying to run a Flask API inside a Docker container. After running the container I get the following on terminal-
* Serving Flask app 'return-nlp' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://172.17.0.2:3000/ (Press CTRL+C to quit)
On sending a POST request on the given URL, I don't get any response. I have also tried sending the same request to http://127.0.0.1:3000/, my own IP Address but I don't get any response from the container and get the two responses on Postman-
Error: connect ECONNREFUSED 127.0.0.1:3000
Error: connect ETIMEDOUT

thanks to #KalusD. for suggesting using the -p option to publish the port on the host machine, this seems to have solved the issue.
we use the -p option to bind the port from the process running in the container to the port on the host machine
--publish , -p Publish a container's port(s) to the host
Check here for more info from the official docs.

Related

Flask App in Docker Container not accessible

I have a simple flask app, which runs in a docker container, which I do not want to access via the localhost. Therefore I set the host = "0.0.0.0".
Flask App:
if __name__ == "__main__":
app.run(
debug=True
, use_reloader = False
, host = "0.0.0.0"
)
When I run this locally everything works as expected.
Then I build my Docker with the following parameters:
# tell the port number the container should expose
EXPOSE 5000
# run the application
CMD ["python", "/usr/src/app/main.py" ]
Afterwards I build my docker container with the following command:
docker build -t my_app:latest .
and run it:
docker run -p 5000:5000 my_app:latest
It starts the container:
* Serving Flask app 'main' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on all addresses (0.0.0.0)
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://127.0.0.1:5000
* Running on http://172.17.0.2:5000 (Press CTRL+C to quit)
Somehow thecontainer is now running on two adresses and only http://127.0.0.1:5000 is accessible.
I already tried various proposed solution but cannot find a solution for my issue.
Thank you for your help!

Handling HTTPS post request in python flask

I have made a simple python flask program :
# save this as app.py
from flask import request
from flask import Flask
app = Flask(__name__)
#app.route("/", methods=['POST'])
def hello():
return "Hello, World!"
#app.route("/sms", methods=['POST'])
def sms():
print(request.get_json())
return "sms world"
if __name__ == '__main__':
app.run(port=443, host='0.0.0.0', ssl_context='adhoc')
This handles the HTTP post request. How can I make it handle HTTPS post requests?
When I execute the command flask run I get the following:
Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server
instead. * Debug mode: off * Running on http://127.0.0.1:5000/
(Press CTRL+C to quit)
So it still uses HTTP instead of https
pip install pyopenssl
When you run the script (or start with flask run if you prefer), you will notice that Flask indicates that it is running an https:// istance
first install pyopenssl with the command:
pip install pyopenssl
to launch it in https just add the parameter: ssl_context='adhoc'
if __name__ == '__main__':
app.run(port=443, host='0.0.0.0', ssl_context='adhoc')
Once started the following message will be shown:
* Serving Flask app 'test' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployment.
* Running on https://192.168.0.62:443/ (Press CTRL+C to quit)
Obviously then once the application goes into production this parameter will no longer be needed, but you will have to set your wsgi to communicate in https
You can try ngrok, it is a useful tool to deploy an HTTPS and HTTP service from local to public net.
https://ngrok.com/

Docker/Flask: Development server runs on localhost fine, but cannot access external URL

I'm brand new to Docker so I think there's something wrong in my setup.
Here's my app.py (reduced version):
import flask
from flask import request
from flask_cors import CORS, cross_origin
app = flask.Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
#app.route('/', methods=['GET'])
#cross_origin()
def index():
return('Home')
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
My Dockerfile:
FROM python:3
WORKDIR /app
ENV FLASK_APP=app.py
COPY ./requirements.txt .
RUN pip3 install -r requirements.txt
COPY . .
CMD ["python3", "app.py"]
I'm building the image with docker build -t flaskapi . and running with
docker run --rm -it -p 80:5000 flaskapi which gives the following output:
* Serving Flask app "app" (lazy loading)
* Environment: development
* Debug mode: on
* Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://172.17.0.2:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
Visiting localhost in the browser, everything works fine but when trying to vist http://172.17.0.2:5000/ or testing with Postman, I eventually get a timeout error. I feel like it's just a small mistake I've made somewhere but I can't quite see it. What can I do to fix this?
By default, Docker runs in a separate subnet that is not accessible by the outside world. To be able to access the service running inside the container, you will have to map one of your host's ports to the internal docker subnet.
In your run command, you map TCP 80 to TCP 5000 inside the docker network (the -p 80:5000 part). That's why your service is accessible when visiting http://localhost (80 is implied). In essence, any request to your port 80 will end up being served by the service running at http://172.17.0.2:5000/.
The 172.* ip is in Docker's subnet range. To communicate via that, with your current settings, you would have to be in another container that shares the same network as this one.

python flask to production server

I have made a small API to connect to a database using Flask.
When I run it I get this output on local (which works fine in postman)
* Serving Flask app "main" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
I want to run this file (main.py) on a server that I have at 172.22.98.254. But when I run it there it still gives me this output:
* Serving Flask app "main" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
So, when I use my postman doing this
where my post URL is http://172.22.98.254:5000/test, How can I use this from the server that I have. I have an ubuntu server.
By default, app.run() hosts server on localhost(127.0.0.1). To make it accessible,
app.run('0.0.0.0', port=5000)
Although, the server bundled with Flask is not for production, it is recommended to use WSGI server(mod_wsgi, nginx, gunicorn, etc.)
https://flask.palletsprojects.com/en/1.0.x/deploying/wsgi-standalone/
I have changed the host default ip address to server or Local network computer ip address. it works fine. My local ip address is 192.168.1.34, using same port as 5000.
app.run(host='192.168.1.34', port=5000)

Google Cloud App Engine: 502 Bad Gateway (nginx) error with Flask App

I am running a Flask app on Google Cloud App Engine (flex). Running it locally works just fine, but once it deploys I get a 502 Bad Gateway error (nginx). Now I would like to figure out what causes this, but I am not able to find any option to view the console logs that my app creates.
Since it works just fine on my local environment, my current workflow to solve this issue involves changing my code locally and deploying it to see if it works afterwards, but each deployment takes over 30min only to figure out it still does not work. There must be a way to do this more efficiently.
Following the docs https://cloud.google.com/appengine/docs/flexible/python/debugging-an-instance
I was able to SSH into my instance in debug-mode and launch the Flask app from the Cloud Shell, however it tells me to access it on http://127.0.0.1:8080/ which I can't access from the cloud server. Hence I can't navigate the webpage in order to reproduce the 502 error and then see the output in the console.
How can I figure out what causes the 502 error on the server?
Had the similar issue.
Found that app engine looks for app variable in main.py file.
My final app.yaml looks like below.
app.yaml
runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app
runtime_config:
python_version: 3
and had requirements.txt, which looks like below.
requirements.txt
Flask==1.1.1
gunicorn==20.0.4
Here are my theories:
localhost (127.0.0.1) is being used; should use 0.0.0.0
Flask internal WSGI server is being used; should use e.g. Gunicorn
NB You may develop and test these solutions using Cloud Shell. Cloud Shell (now) includes a web preview feature that permits browsing endpoints (including :8080) for servers running on the Cloud Shell instance.
Flask
Flask includes a development (WSGI) server and tutorials generally include:
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8080, debug=True)
Which, if run as python somefile.py will use Flask's inbuilt (dev) server and expose it on localhost (127.0.0.1).
This is inaccessible from other machines:
* Serving Flask app "main" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:8080/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 244-629-469
If instead, host='0.0.0.0' is used, then this will work:
* Serving Flask app "main" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 244-629-469
192.168.9.1 - - [08/May/2019 23:59:59] "GET / HTTP/1.1" 200 -
192.168.9.1 - - [08/May/2019 23:59:59] "GET /favicon.ico HTTP/1.1" 404 -
E.g. Gunicorn
Flask's inbuilt server should not be used and Flex's documentation describes how to use gunicorn (one of various alternatives) should be configured:
https://cloud.google.com/appengine/docs/flexible/python/runtime#application_startup
Which, if run gunicorn --bind=0.0.0.0:8080 main:app gives:
[INFO] Starting gunicorn 19.9.0
[INFO] Listening at: http://0.0.0.0:8080 (1)
[INFO] Using worker: sync
[INFO] Booting worker with pid: 7
App Engine Flex
Using the recommended configuration, app.yaml would include:
runtime: python
env: flex
entrypoint: gunicorn --bind:$PORT main:app
Dockerfiles
You can test these locally with Dockerfiles and -- if you wish -- deploy these to Flex as custom runtimes (after revising app.yaml):
FROM python:3.7-alpine
WORKDIR /app
ADD . .
RUN pip install -r requirements.txt
For Flask add:
ENTRYPOINT ["python","main.py"]
NB In the above, the configuration results from the somefile.py app.run(...)
And for gunicorn:
ENTRYPOINT ["gunicorn","--bind=0.0.0.0:8080","main:app"]

Categories

Resources