Я разрабатываю свое веб-приложение, используя Docker + Nginx + Gunicorn + Flask + MySQL, и успешно настроил мое приложение для ответа на HTTP-запросы с помощью простой строки. Однако, когда я пытаюсь сделать вызов MySQL (через экземпляр класса Python, см. Пример ниже), мое приложение возвращает ошибку 502 неверного шлюза. Есть некоторые полезные руководства по этому типу проблемы (https://www.datadoghq.com/blog/nginx-502-bad-gateway-errors-gunicorn/#gunicorn -isnt-running ), и переполнение стека изобилует похожими примерами, но, похоже, ничто не решает мою конкретную проблему c.
Я пришел к выводу, что это вызвано проблемами с сервером WSGI, когда задействована функция MySQL: после проб и ошибок, когда я запускаю Flask приложение напрямую (используя атрибут «cmd» в моем файле docker -compose.yml), вся система работает должным образом - хотя это не рекомендуется, поскольку мои журналы полны предупреждений Flask о том, что его следует запускать через сервер WSGI. Однако это позволило мне проверить, что MySQL все работает нормально. Однако, когда я запускаю приложение Flask через сервер WSGI (Gunicorn, снова используя команду «cmd» в моем файле docker -compose.yml), приложение возвращает 502 ошибки, когда я пытаюсь попасть в конечную точку, которая вызывает MySQL function.
Я проверил с библиотеками uWSGI и Gunicorn (в настоящее время я использую Gunicorn), и проблема точно такая же - отвечать строками верните нормально, все, что связано с использованием команды MySQL, возвращает ошибку 502.
Вот мои настройки Gunicorn (заданные в качестве переменной среды в контейнере Docker с использованием смонтированного файла .env): GUNICORN_CMD_ARGS=--bind=0.0.0.0:8000 --workers=1 --threads=1 --max-requests=0 --keep-alive=5 --log-level debug
Я получаю эти ошибки, зарегистрированные в Docker:
-nginx container name- | -timestamp- [error] 7#7: *20 upstream prematurely closed connection while reading response header from upstream, client: 172.21.0.1, server: localhost, request: "GET /folder/page HTTP/1.1", upstream: "http://172.21.0.3:8000/folder/page", host: "localhost:5000"
-app container name- | -timestamp- [14] [INFO] Booting worker with pid: 14
Вот мое Flask приложение. Как только я закомментирую переменную 'tests', все работает (хотя она возвращает только регистрацию автомобиля):
import logging,sys
from flask import Flask,render_template,request
from classes import Vehicle
app = Flask(__name__)
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
@app.route("/")
def index():
print(request.headers)
user = {'username' : 'Mario'}
posts = [
{
'author': {'username': 'John'},
'body': 'Beautiful day in Portland!'
},
{
'author': {'username': 'Susan'},
'body': 'Beautiful day in Seattle!'
}
]
return render_template('index.html',title='Home',user=user,posts=posts)
@app.route("/reg/<reg_no>")
def regroute(reg_no):
car = Vehicle(reg_no)
tests = car.MethodThatCallsMySQL()
return f"<html><head></head><body>{car.registration}<br>{car}</body></html>"
Вот мой класс Vehicle. Я удалил запрос, но он был протестирован для работы в моем объяснении выше.
import os,mysql.connector,logging,sys
from mysql.connector.errors import Error
logger = logging.getLogger('dev')
logger.setLevel(logging.DEBUG)
class Vehicle(object):
def __init__(self,registration):
self.host = os.environ['HOST']
self.user = os.environ['USER']
self.pw = os.environ['PASSWORD']
self.database = os.environ['DATABASE']
self.registration = registration
def MethodThatCallsMySQL(self):
try:
db = mysql.connector.connect(host=self.host,user=self.user,password=self.pw,database=self.database)
query = --query that has been tested to work—-
cur = db.cursor(dictionary=True)
cur.execute(query,(self.registration,))
results = cur.fetchall()
cur.close()
return results
except Error as e:
logger.error(e)
except UnboundLocalError as ule:
logger.error(ule)
except Exception as ex:
logger.error(ex)
finally:
db.close()
Файл WSGI, который я запускаю, относительно прост. Я также попытался добавить аргумент debug=True
к app.run()
, и у меня возникла та же проблема:
from routes import app
if __name__ == "__main__":
app.run()
Наконец, вот мой файл docker -compose.yml:
version: "3.7"
services:
web-nginx:
build: ./network
image: containername/nginx
volumes:
- type: bind
source: ./static
target: /home/static
ports:
- "5000:5000"
web-app:
build: ./app
image: containername/app
env_file:
- ./credentials/app-variables.env
- ./app/gunicorn.env
command: gunicorn wsgi:app
#I have tested running the Flask application directly by calling the wsgi program (the program then responds with the current information from DB. This is how I did it:
#command: python wsgi.py
dwh:
image: mysql:8
volumes:
- type: bind
source: ./extractor/db/setup
target: /docker-entrypoint-initdb.d
env_file:
- ./credentials/db-variables.env
Поиск похожих проблем в StackOverflow предполагает проблему с памятью, но моя статистика Docker предполагает очень низкое использование памяти. Я застрял и ищу совета.
Спасибо