How to deploy a Flask app to Google Cloud (App Engine) with an application factory, and how to write the app.yaml file?
Question:
I found a similar question here but the solution did not work for me.
I have written a Flask app by following the official tutorial. I am trying to deploy it with Google App Engine. I have used Blueprints. The directory structure of my app looks like this:
app
│ .gcloudignore
│ app.yaml
│ main.py
│ requirements.txt
│ __init__.py
│
├───googleutils
│ │ utils.py
│
├───home
│ │ home.py
│ │
│ ├───static
│ ├───templates
│ │ home.html
│
├───models
│ │ Message.py
│ │ User.py
│
├───profile
│ │ profile.py
│ │
│ ├───static
│ ├───templates
│ │ edit_message.html
│ │ profile.html
│
├───sessions
│ │ sessions.py
│ │
│ ├───templates
│ │ login.html
│ │ logout.html
│ │ register.html
│
├───static
│ style.css
│
├───templates
│ layout.html
│ wrapper.html
In my app directory I have my app.yaml
and requirements.txt
. I used pip freeze
in my venv and just chucked everything it spat out into requirements.txt
.
The current Flask tutorial instructs you to start your app via command line using flask run
. Hence, my application starts from __init__.py
:
from flask import Flask
def create_app():
app = Flask(__name__, instance_relative_config=True)
# Application imports
from .home import home
from .sessions import sessions
from .profile import profile
# Blueprints
app.register_blueprint(home.home_bp)
app.register_blueprint(sessions.sessions_bp)
app.register_blueprint(profile.profile_bp)
return app
However, as noted in the question I linked above, gcloud looks for a main.py
, so I added this to my root:
from app import create_app
app = create_app()
At the moment I’m just trying to get my index loaded, which is defined in home.py
:
@home_bp.route('/', methods=['GET', 'POST'])
def home():
...
Here’s my app.yaml:
runtime: python39
entrypoint: gunicorn "app:create_app()"
handlers:
- url: /static
static_dir: static
- url: /.*
script: auto
Truth be told I have no idea how to write this file, especially for directories with variables, such as this one defined in profile.py
:
@profile_bp.route('/profile/<string:user_id>', methods=['GET', 'POST'])
def profile(user_id):
...
When I run gcloud app deploy
, I get a 500 Server Error when I view my site in-browser, "The server encountered an error and could not complete your request.".
What am I doing wrong?
Answers:
Well, I figured it out. My directory structure was wrong. It SHOULD be:
│ app.yaml
│ main.py
│ requirements.txt
├───app
│ │ __init__.py
│ └
Where app.yaml
contains only:
runtime: python39
handlers:
- url: /.*
script: auto
Which causes GCloud to automatically look for the main.py
file containing:
from app import create_app
app = create_app()
The whole webapp works this way.
Does it have to be called main.py or is it calling for app = create_app()?
I found a similar question here but the solution did not work for me.
I have written a Flask app by following the official tutorial. I am trying to deploy it with Google App Engine. I have used Blueprints. The directory structure of my app looks like this:
app
│ .gcloudignore
│ app.yaml
│ main.py
│ requirements.txt
│ __init__.py
│
├───googleutils
│ │ utils.py
│
├───home
│ │ home.py
│ │
│ ├───static
│ ├───templates
│ │ home.html
│
├───models
│ │ Message.py
│ │ User.py
│
├───profile
│ │ profile.py
│ │
│ ├───static
│ ├───templates
│ │ edit_message.html
│ │ profile.html
│
├───sessions
│ │ sessions.py
│ │
│ ├───templates
│ │ login.html
│ │ logout.html
│ │ register.html
│
├───static
│ style.css
│
├───templates
│ layout.html
│ wrapper.html
In my app directory I have my app.yaml
and requirements.txt
. I used pip freeze
in my venv and just chucked everything it spat out into requirements.txt
.
The current Flask tutorial instructs you to start your app via command line using flask run
. Hence, my application starts from __init__.py
:
from flask import Flask
def create_app():
app = Flask(__name__, instance_relative_config=True)
# Application imports
from .home import home
from .sessions import sessions
from .profile import profile
# Blueprints
app.register_blueprint(home.home_bp)
app.register_blueprint(sessions.sessions_bp)
app.register_blueprint(profile.profile_bp)
return app
However, as noted in the question I linked above, gcloud looks for a main.py
, so I added this to my root:
from app import create_app
app = create_app()
At the moment I’m just trying to get my index loaded, which is defined in home.py
:
@home_bp.route('/', methods=['GET', 'POST'])
def home():
...
Here’s my app.yaml:
runtime: python39
entrypoint: gunicorn "app:create_app()"
handlers:
- url: /static
static_dir: static
- url: /.*
script: auto
Truth be told I have no idea how to write this file, especially for directories with variables, such as this one defined in profile.py
:
@profile_bp.route('/profile/<string:user_id>', methods=['GET', 'POST'])
def profile(user_id):
...
When I run gcloud app deploy
, I get a 500 Server Error when I view my site in-browser, "The server encountered an error and could not complete your request.".
What am I doing wrong?
Well, I figured it out. My directory structure was wrong. It SHOULD be:
│ app.yaml
│ main.py
│ requirements.txt
├───app
│ │ __init__.py
│ └
Where app.yaml
contains only:
runtime: python39
handlers:
- url: /.*
script: auto
Which causes GCloud to automatically look for the main.py
file containing:
from app import create_app
app = create_app()
The whole webapp works this way.
Does it have to be called main.py or is it calling for app = create_app()?