Flask / Docker: Error: Could not import 'project.main.python' - python

I am trying to build and run a flask application using docker on GCP.
My file structure is as follows:
> /project
> static (contains some images)
> templates (contains html files)
> tmp_data (contains some data that is created during usage of the app)
> __init__.py
> auth.py (app has a login feature, this script helps authorize them)
> main.py
> Dockerfile
> some other function scripts
My Dockerfile is as follows:
FROM python:3.9-slim
RUN pip3 install Flask gunicorn scipy seaborn matplotlib pandas numpy flask_excel flask_login flask_sqlalchemy
COPY . /project
WORKDIR project
ENV FLASK_APP=main.python
# run flask in dev mode
ENV FLASK_ENV=development
EXPOSE 5001:5000
CMD ["flask", "run", "--host", "0.0.0.0"]
My main.py file is as follows:
from flask import Blueprint, render_template, redirect, url_for
from flask_login import login_required, current_user
from . import db
import flask_excel as excel
import json
# user written imports (not sure why it wants relative imports now?)
from .generate_data import get_truncated_normal, create_data
from .create_graphs import plot_graph, hist_plot, bar_plot, pie_plot, data_comments
from .generate_html_file import generate_html
main = Blueprint('main', __name__)
#main.route('/')
def index():
return render_template('index.html')
... some functions and flask views ...
When I build my app (successfully) using the command
~/some_upper_folder/project (my_sandbox)$ docker build -t project .
and then run it with the command
~/some_upper_folder/project (my_sandbox)$ docker run project
I get the error:
* Serving Flask app 'main.python' (lazy loading)
* Environment: development
* Debug mode: on
Usage: flask run [OPTIONS]
Try 'flask run --help' for help.
Error: Could not import 'project.main.python'.
I am not sure why this is occurring, I'm guessing this is due to the fact that I'm referencing an incorrect directory?
NOTE: The app is working correctly, I can run it using a venv created in another folder not seen here

Related

Flask App runs in terminal but not in Docker Container

So, I've got this flask app that works fine when I run it via the terminal, but for some reason, if I start up a docker container, it instantly exits with 'exit code zero'.
Here is the folder structure:
https://imgur.com/a/BOGCt6S
docker-compose.yml:
version: '3.2'
services:
flask-app:
build: ./Flask_App
volumes:
- ./Flask_App/static:/Flask_App/static
- ./Flask_App/db:/Flask_App/db
ports:
- '5001:5001'
# restart: unless-stopped
Dockerfile:
FROM python:3
# Setup env
COPY requirements.txt ./
RUN pip install -r requirements.txt
# Setup App
RUN mkdir -p /Flask_App
COPY . /Flask_App
WORKDIR /Flask_App
EXPOSE 5001
ENTRYPOINT [ 'python3' ]
CMD [ 'app.py' ]
and the app.py file: (I know its just imports, but it works fine when I run it via the terminal on the host, so it probably is working ok)
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_bootstrap import Bootstrap
from forms import *
app = Flask(__name__)
app.config.from_pyfile('config.py')
Bootstrap(app)
db = SQLAlchemy(app)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
from views import *
if __name__ == '__main__':
app.run(host=app.config['HOST'], port=app.config['PORT'], debug=app.config['DEBUG'])
and just in case, here is a part of the 'config.py' file:
DEBUG = False
HOST = '0.0.0.0'
PORT = 5001
As said by David Maze in a comment, the single quotes(') I used in ENTRYPOINT and CMD should be changed to double quotes ("), since they are supposed to be JSON arrays.

Python flask app container image cannot resolve internal modules

I have created a simple python flask API project using pycharm. It works great when I run using IDE and API's can be tested without any problem on localhost. BUT when I create a docker image of it and run the container on localhost, it always throw following error:
Traceback (most recent call last):
File "./app.py", line 2, in <module>
from application import db, application
ModuleNotFoundError: No module named 'application'
It has following directory structure
MyFlaskAPI
|
-Application
|
- __init__.py
|
-Models
|
-Model.py
|
-- Other project folders e.g. template, include, libs etc
|
- app.py
- config.py
- requirements.txt
- Dockerfile
- Few other config files
init.py looks is as follows:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config.from_object('config')
db = SQLAlchemy(app)
app.py is as follows:
from flask import request
from application import db, app
from model.models import FirstModel, SecondItemModel, ThirdModel
Docker file as follows:
FROM python:3
ADD app.py /
ADD requirements.txt /
RUN pip install -r requirements.txt
#EXPOSE 5000
CMD [ "python", "./app.py", "--host", "0.0.0.0"]
dockerfile
FROM python:3
ADD app.py /
ADD requirements.txt /
RUN pip install -r requirements.txt
#EXPOSE 5000
CMD [ "python", "./app.py", "--host", "0.0.0.0"]
Any suggestions/help is highly appreciated.

How to setup the startup command for a flask azure web app

I've created a simple flask web app and managed to publish it with CI/CD from azure devops to an azure web app. The pipelines are working except the startup of my app.
If i look at the log files in the webapp this comes up -
logfile default_docker.log:
2020-01-08T13:04:17.017575225Z Documentation: http://aka.ms/webapp-linux
2020-01-08T13:04:17.017579025Z Python 3.7.5
2020-01-08T13:04:17.017582725Z Note: Any data outside '/home' is not persisted
2020-01-08T13:04:17.093756525Z Starting OpenBSD Secure Shell server: sshd.
2020-01-08T13:04:17.109540649Z Site's appCommandLine: gunicorn --bind = 0.0.0.0 --timeout 600 app: application
2020-01-08T13:04:17.110379356Z Launching oryx with: -appPath /home/site/wwwroot -output /opt/startup/startup.sh -virtualEnvName antenv -defaultApp /opt/defaultsite -bindPort 8000 -userStartupCommand 'gunicorn --bind = 0.0.0.0 --timeout 600 app: application'
2020-01-08T13:04:17.114336587Z Oryx Version: 0.2.20191105.2, Commit: 67e159d71419415435cb5d10c05a0f0758ee8809, ReleaseTagName: 20191105.2
2020-01-08T13:04:17.116548105Z Found build manifest file at '/home/site/wwwroot/oryx-manifest.toml'. Deserializing it...
2020-01-08T13:04:17.118951024Z Build Operation ID: |DGaRVt5jG5c=.2a144509_
2020-01-08T13:04:17.554659456Z Writing output script to '/opt/startup/startup.sh'
2020-01-08T13:04:17.784203265Z Found virtual environment .tar.gz archive.
2020-01-08T13:04:17.784884970Z Removing existing virtual environment directory /antenv...
2020-01-08T13:04:17.788272497Z Extracting to directory /antenv...
2020-01-08T13:04:32.810295030Z Using packages from virtual environment antenv located at /antenv.
2020-01-08T13:04:32.817794689Z Updated PYTHONPATH to ':/antenv/lib/python3.7/site-packages'
2020-01-08T13:04:36.780635398Z usage: gunicorn [OPTIONS] [APP_MODULE]
2020-01-08T13:04:36.780670499Z gunicorn: error: unrecognized arguments: app: application
my simplefied app treeview looks like this -
test_app/
venv/
application/
templates/
__init__.py
routes.py
errors.py
models.py
forms.py
app.py
i've tried different startup commands in azure portal "general setting" but to no solution
gunicorn --bind=0.0.0.0 --timeout 600 app:application
EDIT : added app.py and init.py
app.py:
from application import app, db
from application.models import User, Post
#app.shell_context_processor
def make_shell_context():
return {'db': db, 'User': User, 'Post': Post, 'Classrooms' : Classrooms, 'ClassSession' : ClassSession, 'Teacher' : Teacher}
init.py
from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
from logging.handlers import RotatingFileHandler
import os
from flask_bootstrap import Bootstrap
import logging
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
login = LoginManager(app)
login.login_view = 'login'
bootstrap = Bootstrap(app)
from application import routes, models, errors
if __name__ == '__main__':
# * --- DEBUG MODE: --- *
app.run(host='127.0.0.1', port=5000, debug=True)
can anybody point me a direction to where i can solve this stupid problem.
thx a lot!!
The gunicorn command isn't actually pointing to the WSGI app object. Try this instead:
gunicorn --bind=0.0.0.0 --timeout 600 application:app

Error: gunicorn: Failed to find application object 'app' in 'app'

Here's my code:
app.py
from flask_graphql import GraphQLView
from app.infrastructure.graphql import schema
from app.infrastructure.api_resource import app
app.add_url_rule('/graphql', view_func=GraphQLView.as_view('graphql', schema=schema, graphiql=True))
if __name__ == '__main__':
app.run(debug=True)
api_resource.py
import app.infrastructure.repository as repository
from flask import request, url_for
from flask_restplus import Api, Resource, fields
from sqlalchemy_pagination import paginate
from sqlalchemy_fulltext import FullTextSearch
app = repository.app
api = Api(app, version='0.1', title='xxxxx',
description='xxxxx')
...
repository.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from app.domain.model import Base
connection_string = 'xxxxxx'
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = connection_string
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app, metadata=Base.metadata)
However, when i execute the gunicorn command "gunicorn app: app" i get this error:
Failed to find application object 'app' in 'app'
I'm using pipenv whith pipenv shell on ubuntu 16.04, but i've also tried on a docker container and got the same error.
here's my pip file:
[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"
[dev-packages]
[packages]
flask-graphql = "*"
flask-sqlalchemy = "*"
sqlalchemy-fulltext-search = "*"
graphene-sqlalchemy = ">=2.0"
flask-marshmallow = "*"
sqlalchemy-pagination = "*"
flask-restplus = "*"
requests = "*"
mysqlclient = "*"
gunicorn = "*"
[requires]
python_version = "3.6"
What am i doing wrong?
You have a folder called app (as by the import lines in your file) and a app.py file.
Gunicorn will try to find the app WSGI variable inside the app module, which in your case is identified as app/__init__.py
You need to rename your folder or your app.py file to avoid this conflict.
I found that this bug only happens on gunicorn version 20+. When I downgrade to version 19.9.0, it works fine even with the folder and app.py sharing the same name.
Accepted answers might be spot on for the original question , however I got the same error and I was running the gunicorn command as :
gunicorn app
In my case neither renaming the app.py nor downgrading worked.
Following fixed the issue:
gunicorn app:app
After a lot of trial and error trying to change things in init files and the dockerfile, this is what we ended up with, in our gunicorn/conda/Docker stack:
Dockerfile:
FROM continuumio/miniconda3
WORKDIR /app
# create environment
COPY environment.yml /app
RUN conda env create --name my_app_env --file environment.yml
# ensure RUN commands use the new environment
SHELL ["conda", "run", "-n", "my_app_env ", "/bin/bash", "-c"]
COPY . .
EXPOSE 8123
ENTRYPOINT [\
"conda", "run", "--no-capture-output", "-n", "my_app_env ",\
"gunicorn", "-b", "0.0.0.0:8123",\
"--pythonpath", "src/MyApp",\
"src.MyApp.app:server"\
]
Dir structure:
MyApp
|- src
|- MyApp
- __init__.py (file is empty for now)
- app.py
- Dockerfile
- environment.yml
- setup.py
initialisation in app.py
server = flask.Flask(__name__)
app = Dash(__name__, suppress_callback_exceptions=True, server=server)
)```

Docker+Gunicorn+Flask, I don't understand why my setup is not working

I'm trying to build a simple application with flask and I've decided to also use gunicorn and docker.
At the moment I have this configuration:
> app
> myapp
__init__.py
index.html
docker-compose.yml
Dockerfile
My docker-compose.yml:
version: '2'
services:
web:
build: .
volumes:
- .:/app
command: /usr/local/bin/gunicorn -b :8000 myapp:app
working_dir: /app
My __init__.py:
import os
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def home():
return render_template('index.html')
if __name__ == '__main__':
app.run()
This minimal configuration works and I'm able to access my application and get my index page.
What I don't like is having my app created inside the __init__.py so I would like to move the app creation inside an app.py file.
The new structure will be:
> app
> myapp
__init__.py
app.py
index.html
docker-compose.yml
Dockerfile
app.py will have the content of the old __init__.py file and the new __init__.py file would be empty.
This doesn't work. I get an error
Failed to find application: 'myapp'
and I don't understand why.
Any idea about this?
In the first configuration, your Flask app was located directly in the package myapp; after you moved it, it is in the module myapp.app.
Gunicorn expects the app to be specified as module_name:variable_name, somewhat like from module_name import variable_name.
Option one: specify the correct module path:
/usr/local/bin/gunicorn -b :8000 myapp.app:app
Option two: add the app back to myapp. In myapp/__init__.py, add
from .app import app
Note that if the variable and the module share the name, the module will be overshadowed (not a good thing, although not a critical either).

Categories