Configuring python flask app in HTTPS mode in OpenShift [duplicate] - python

This question already has answers here:
Are a WSGI server and HTTP server required to serve a Flask app?
(3 answers)
Closed 1 year ago.
This post was edited and submitted for review 1 year ago and failed to reopen the post:
Original close reason(s) were not resolved
I am trying to run a python flask app in https mode in openshift 4.7. I have my python flask app listening at port 8080 and this port is exposed through dockerFile configuration as shown below. I have redirected the https requests through the configuration in Openshift console by doing Service Port Mapping for https port 443 to pod port 8080. You can configure this by going to Openshift Console > Project > Services > Service Details and select your app. But still I can't access the service in https mode. When I try to access in https mode I get the error The application is currently not serving requests at this endpoint. It may not have been started or is still starting.
When I do normal deployment through oc cli and do not do any ssl configuration through openshift console, the app works fine in http mode. Please advise on how to run this in https mode
my app.py code is below
from flask import Flask, jsonify, request, redirect
app = Flask(__name__)
#app.route('/<string:name>/')
def helloName(name):
print(request)
return "Hello " + name
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080, debug = True)
my Dockerfile content is as below and I am exposing port 8080 from it
# set base image
FROM registry.redhat.io/rhel8/python-38
# copy the dependencies file to the working directory
COPY requirements.txt .
# Configure PIP with local Nexus
ENV PIP_TRUSTED-HOST=nexus.company.com:8443
ENV PIP_INDEX=https://nexus.company.com:8443/repository/pypi-group/pypi
ENV PIP_INDEX-URL=https://nexus.company.com:8443/repository/pypi-group/simple
ENV PIP_NO-CACHE-DIR=false
ENV PIP_TIMEOUT=600
RUN touch ~/.netrc && \
echo "machine nexus.company.com" >> ~/.netrc && \
echo "login ${NEXUS_USER}" >> ~/.netrc && \
echo "password ${NEXUS_TOKEN}" >> ~/.netrc
# install dependencies
RUN pip install -U pip \
pip install -r requirements.txt
# copy the content of the local src directory to the working directory
COPY src/ .
EXPOSE 8080
# command to run on container start
CMD [ "python3", "./app.py" ]
Requirements.txt has only Flask

Two things here:
With host="0.0.0.0" Flask listens to the IP of the machine it is running on. I think changing this to 127.0.0.1 should be good.
app.run(host='127.0.0.1', port=8080, debug = True)
Probably even more important, the .run() method from Flask is only for development, for production you should use something like gunicorn or something.
link: https://gunicorn.org/
Cheers, T

Related

SMTPServerDisconnected When Sending via Flask-Mail on Gunicorn

I have a Flask app deployed with Gunicorn & Nginx and I am trying to debug a strange issue I am having with sending emails from the application (via Flask-Mail library). Sending emails works from my local development environment and also works on my server (on Digital Ocean) if I start my application via the flask run command. This is important as most of the answers I have found mention that their hosting provider blocks outgoing mail over the default SMTP port.
Once I try to send any email from the application hosted in Gunicorn I get the following error in my logs -
File "/usr/lib/python3.10/smtplib.py", line 365, in send
raise SMTPServerDisconnected('please run connect() first')
smtplib.SMTPServerDisconnected: please run connect() first
My application is launched in Gunicorn via the below command -
gunicorn --workers 3 \
--timeout 120 \
--bind 0.0.0.0:9000 \
--log-file=dt.log \
--bind unix:dt.sock -m 007 \
--log-level=info wsgi:app
I have created a very simple route to send an email and I see the same behavior as my existing code. This is the route I created.
#bp.route("/debugmail")
def debugmail():
msg = Message(
"An Email Subject!",
sender=("Email Sender Name", "emailfromsample#gmail.com"),
recipients=["ping#pong.com"],
)
msg.body = "This is an email from the App (tons of uses for this)."
# Also Tried Adding the Connect Command Here
# mail.connect()
mail.send(msg)
return {"message": "Email sent!"}, 200
The configuration file I use for this app is below -
MAIL_SERVER=smtp.gmail.com
MAIL_PORT=587
MAIL_USE_TLS=True
MAIL_USE_SSL=False
MAIL_USERNAME=username#gmail.com
MAIL_PASSWORD=app-specific-password
Any help or thoughts or tests for me to run would be greatly appreciated!
It turns out that by using a .env file that Flask was able to read automatically, was not passed into the context of the Gunicorn runner.
As per the answer linked belo, I have created this file which guarantees that both my .flaskenv and .env load no matter the context.
Running flask app with gunicorn and environment variables
# gunicorn.conf.py
import os
from dotenv import load_dotenv
for env_file in ('.env', '.flaskenv'):
env = os.path.join(os.getcwd(), env_file)
if os.path.exists(env):
load_dotenv(env)

Refused to connect local ip address by using docker while running ok without docker [duplicate]

This question already has answers here:
Deploying a minimal flask app in docker - server connection issues
(8 answers)
Closed 7 months ago.
[Editted]
I am trying to dockerize a simple flask project. I kept getting this error when I run the project using docker. On the other hand the project works just fine when I run it normally using python3 test-flask.py
Docker File
FROM python:3.9.6-slim
# https://www.lifewithpython.com/2021/05/python-docker-env-vars.html
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PYTHONUTF8=1 \
PIP_DISABLE_PIP_VERSION_CHECK=on
RUN apt-get update \
&& apt-get install --no-install-recommends -y \
curl \
wget \
unzip \
jq \
ffmpeg \
libsndfile1-dev \
&& rm -rf /var/lib/apt/lists/*
RUN wget "https://download.pytorch.org/whl/cpu/torch-1.10.2%2Bcpu-cp39-cp39-linux_x86_64.whl" \
&& pip install torch-1.10.2+cpu-cp39-cp39-linux_x86_64.whl
RUN mkdir app
WORKDIR /app
COPY README.md .
COPY requirements.txt .
COPY setup.py .
COPY src ./src
RUN pip install .
# COPY main.py .
COPY test_flask.py .
CMD [ "python", "test_flask.py", "run", "--host", "0.0.0.0"]
docker-compose.yml
version: '3.9'
services:
asr-cpu-local:
build:
context: ./
dockerfile: ./Dockerfile
volumes:
- ./data:/data
- ./models:/models
ports:
- 127.0.0.1:8000:8000
In the Terminal and Docker Container log, after I run it with docker, it shows no error at all
* Serving Flask app 'test_flask' (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 http://127.0.0.1:8000 (Press CTRL+C to quit)
* Restarting with stat
For additional information, I have run docker port to check, but the error still occured:
docker port <container-name>
8000/tcp -> 127.0.0.1:8000
For the File test_flask.py:
from flask import Flask
app = Flask(__name__)
import librosa
from src.jrasr.predictors import Wav2vec2bert2bertPredictor
MODEL_CONFIG = {
"name": "Wav2vec2bert2bertPredictor",
"version": "0.0.1",
"models": [
{
"name": "wav2vec2",
"dir": "/models/wav2vec2-base-csj-kana-v0.0.1"
},
{
"name": "bert2bert",
"dir": "/models/bert2bert-csj-kana-v0.0.1"
}
]
}
#app.before_first_request
def load_model_to_app():
# Load the model
app.predictor = Wav2vec2bert2bertPredictor(MODEL_CONFIG)
#app.route('/')
def index():
return "This is Home Page"
#app.route('/data/<audio_path>')
def predict(audio_path):
model = app.predictor
audio_path = "/data/"+audio_path
data, _ = librosa.load(audio_path, sr=16000, mono=True, duration=10)
words = model.predict(data)
result = "".join(words)
return result
if __name__ == "__main__":
app.run(host="127.0.0.1", port=8000, debug=True)
But when I try to access the Ip address as shown in the Terminal and Docker Container Log, I got that 127.0.0.1 refuse to connect such as in the image shown below. The problem is in the terminal and docker log, there isn't any Error message, but still I can't access it, can anyone tell me, how to solve my problems?
Error at the local browser
127.0.0.1 is the localhost interface and when running inside the container only the container has access to it. To be accessible outside the container it should be the special IP 0.0.0.0 to bind all interfaces.
Solution 1
Change the host to be 0.0.0.0 instead of 127.0.0.1 in the test_flask.py. Something like the following snippet.
WARNING: As 0.0.0.0 binds all interfaces to the outside world it could be a security risk if running it locally instead of in a container. That said, the Solution 2 is the recommended one (With the 127.0.0.1 in the Python source as it is). So, when running it directly locally it binds to the localhost and when running it in the container it binds the outside world of the container itself.
...
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000, debug=True)
Solution 2
On the other hand, to run it passing the host as an argument the Dockerfile should be changed to the following:
...
ENV FLASK_APP=test_flask
CMD ["flask", "run", "--host=0.0.0.0"]
Test it with the browser connecting to http://localhost:8000/ or http://127.0.0.1:8000/

Start docker with flask application using ssl [duplicate]

This question already has answers here:
Deploying a minimal flask app in docker - server connection issues
(8 answers)
Closed 5 years ago.
I've got a flask application with SSL authorization.
Here is my run.py:
#!flask/bin/python
from app import app
import ssl
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ctx.load_cert_chain('sertnew/se-emulator.crt', 'sertnew/se-emulator.key')
app.run(debug=True, host='127.0.0.1', port=5000, ssl_context=ctx)
On my machine, I run it simply with
python run.py
Then I open https://localhost:5000 in chrome and it works (there is a message of non-secure connection, but it's ok for me)
Now I'm trying to make it work in Docker container.
I've got a Dockerfile like this:
FROM python:3.5-slim
RUN apt-get update && apt-get install -y python3-pip
COPY . /storage-emulator
WORKDIR /storage-emulator
RUN pip3 install -r requirements.txt
EXPOSE 5000
ENTRYPOINT ["python"]
CMD ["run.py"]
and try to run it in different ways.
I can see "Running on https://127.0.0.1:5000/ (Press CTRL+C to quit)" message, but can't open the page in the browser. What am I doing wrong?
This is a rather easy fix, you have to change this line:
app.run(debug=True, host='127.0.0.1', port=5000, ssl_context=ctx)
to
app.run(debug=True, host='0.0.0.0', port=5000, ssl_context=ctx)
You have to think from the containers' perspective: The container has its own "localhost", which is different from the localhost of the host machine, all of that means that flask has never received the request.
Therefore you can simply bind to all IPs within the container, which is done by binding to "0.0.0.0".

Docker connection refused on all ports except 5000

I have just started with Docker. I have installed Docker Toolbox for Windows. I was trying out a sample Flask app to understand how things work. But I am stuck!. I am trying to access my app like this http://docker-machine-ip : port number but every time I do, I get '{docker-machine ip} refused to connect.'
I get no exceptions during the building and deploying stages. I also did docker ps to see that container is running. I even tried to access it via Kitematic but still no luck. Below are details related to the app
app.py
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Flask inside Docker shakel!!"
if __name__ == "__main__":
app.run(debug=True,host='0.0.0.0')
requirements.txt
flask
Dockerfile
FROM python:2.7
MAINTAINER Shekhar Gulati "shekhargulati84#gmail.com"
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
ENTRYPOINT ["python"]
CMD ["app.py"]
The docker commands I used for building and running are:
docker-machine ip default //To get docker machine ip
docker build -t flask-app .
docker run -d -p 6000:6000 flask-app
I have Windows 7 64 bit. Please let me know if any more info is required.
P.S. However I noticed that if I map my container to 5000 port it will run fine but on any other port I get connection refused
I don't know what am I missing here. This is my first attempt at Docker and I have googled for 4 hrs to find a solution but nothing is working. So it might be a very dumb mistake I am doing somewhere :).anyhow any help is very much appreciated. Thanks in advance.
That's because you didn't set the port for your flask application, which is port 5000 by default.
From flask documentation:
port – the port of the webserver. Defaults to 5000 or the port defined in the SERVER_NAME config variable if present.

Can't acces swagger server into docker container

I have a swagger server api in python that I can run on my pc and easily access to the user interface via web. I'm now trying to run this API into a docker container and place it into a remote server. After the doing the 'docker run' command int the remote server all seems to be working fine but when I try to connect I got a ERR_CONNECTION_REFUSED response. The funny thing is that if I enter into the container the swagger server is working and answer my requests.
Here is my Dockerfile:
FROM python:3
MAINTAINER Me
ADD . /myprojectdir
WORKDIR /myprojectdir
RUN pip install -r requirements.txt
RUN ["/bin/bash", "-c", "chmod 777 {start.sh,stop.sh,restart.sh,test.sh}"]
Here are my commands to build/run:
sudo docker build -t mycontainer .
sudo docker run -d -p 33788:80 mycontainer ./start.sh
Here is the start.sh script:
#!/bin/bash
echo $'\r' >> log/server_log_`date +%Y%m`.dat
python3 -m swagger_server >> log/server_log_`date +%Y%m`.dat 2>&1
And the main.py of the swagger server:
#!/usr/bin/env python3
import connexion
from .encoder import JSONEncoder
if __name__ == '__main__':
app = connexion.App(__name__, specification_dir='./swagger/')
app.app.json_encoder = JSONEncoder
app.add_api('swagger.yaml', arguments={'title': 'A title'})
app.run(port=80, threaded=True, debug=False)
Does anyone know why I can't acces to 'myremoteserver:33788/myservice/ui' and what to change for solving it.
Thanks in advance
I finally managed to find out the solution. It's needed to tell the flask server of connexion to run on 0.0.0.0 so that not only local connections are allowed and to change in the swagger.yaml the url with the name of the server where the docker container is located
app.run(port=80, threaded=True, debug=False, host='0.0.0.0')

Categories