Skip to main content

Example app

There are many ways to structure a Flask application, so this guide uses a simple example to demonstrate how to deploy a Flask app on Sevalla. The same approach can be adapted to fit most Flask project layouts and use cases. What’s included in the example app:

Database models

This Flask app uses SQLAlchemy for its ORM. Only the Base model is necessary. Any other models for the app inherit from the Base class.
#app/models.py
from sqlalchemy.orm import DeclarativeBase

class Base(DeclarativeBase):
    pass

Extensions

This example only requires two extensions:
  • Flask-SQLAlchemy-Lite: A lightweight extension that integrates SQLAlchemy with Flask, allowing you to configure and manage your database connection using your Flask app’s existing configuration.
  • Flask-Alembic: Provides database migration support for Flask applications, enabling you to generate and apply schema migrations based on your SQLAlchemy models.
# app/extensions.py
from flask_alembic import Alembic
from flask_sqlalchemy_lite import SQLAlchemy

from .models import Base

db = SQLAlchemy()
alembic = Alembic(metadatas=Base.metadata)

Application factory

In __init__.py, the create_app function instantiates the Flask app object, loads config values from environment variables, and initializes both extensions on the Flask app.
# app/__init__.py
from flask import Flask

from .extensions import db, alembic

def create_app():
    app = Flask(__name__)
    app.config.from_prefixed_env()

    db.init_app(app)
    alembic.init_app(app)

    return app

Run file

The Flask development server can automatically discover and run the create_app application factory, but production servers like Gunicorn cannot. To address this, you need to add a separate run.py file that explicitly calls create_app and exposes the application instance for the production server to run.
# run.py
from app import create_app

app = create_app()

App settings file

For this project, all configuration values are read from environment variables prefixed with FLASK_. During development, you can use a .env file to define these values so they’re automatically loaded when the app starts. When deploying to Sevalla, these environment variables can be configured directly through Sevalla instead. This application requires a single configuration value that defines the database connection URL.
# .env
FLASK_SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://<user>:<password>@<hostname>:<port>/<db_name>

Requirements

The following installs all the requirements for this example app:
pip install flask python-dotenv
pip install flask-sqlalchemy-lite flask-alembic
pip install gunicorn psycopg2-binary
pip freeze > requirements.txt

Add a hosted database

The filesystem used for your app will be recreated on each deploy, so an SQLite database isn’t suitable for production. Instead, you can use a hosted database on Sevalla for your app. Create a database in Sevalla and select either Postgres, MySQL, or MariaDB. You also need to install a database driver if you haven’t already done so. For example, with Postgres, you can use psycopg2-binary.
pip install psycopg2-binary

Nixpacks

By default, Sevalla uses Nixpacks to build your application. After you add the application, you need to add custom commands that will both start your app and run migrations before every deploy. To update the start command, go to Processes > Web process > Update process and add gunicorn run:app as your custom start command. For migrations, you can create a job to run the migrate command before the container is started. To do this, after you add your application, go to Processes > Create job > Job. For the start command, add flask db upgrade. The start policy should be before deployment, and the smallest instance size should be sufficient for migrations.

Dockerfile

To build your application from a Dockerfile, you need a Dockerfile that ends with your application being started by Gunicorn or any other WSGI server. The following is a sample Dockerfile that sets up a Python environment, installs your dependencies, and then starts a Gunicorn server.
FROM python:latest  

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1 
 
RUN mkdir /app
WORKDIR /app
 
RUN pip install --upgrade pip 
COPY requirements.txt  .
RUN pip install --no-cache-dir -r requirements.txt
 
COPY . .
 
CMD ["gunicorn", "run:app"]
The command to start Gunicorn must reference the name of the file containing your Flask app object. The rest of the Dockerfile can be customized according to your project’s specific needs.

Migrations

For migrations, you can create a job to run the migrate command before the container is started. To do this, after you add your application, go to Processes > Create job > Job. For the start command, add flask db upgrade. The start policy should be before deployment, and the smallest instance size should be sufficient for migrations.

Build settings

By default, Sevalla builds applications using Nixpacks, so the build strategy must be updated before your Dockerfile can be used. To update the build strategy, after you add your application, go to Settings > Update build strategy and change the build strategy from Nixpacks to Dockerfile.

Deploy on Sevalla

To deploy your app to Sevalla using Git, your code must be hosted in a Git repository. Sevalla supports any public Git repository or private repositories from GitHub, Bitbucket, and GitLab. You’ll need to connect your repo host account with Sevalla if you are using a private repo. Your repo should have a .gitignore that ignores SQLite files, .env files, virtual environments, __pycache__/, any other files that either have sensitive information or don’t need to be tracked in git. Here is an example .gitignore file:
__pycache__/ 
.env
.venv/
env/
venv/
*.sqlite3
You can now add your application in Sevalla and choose the branch and repository for your project. Ensure that you set the location for your application to match the location of your database, allowing them to communicate over an internal network. If your app requires more resources than the defaults of 0.3 GB RAM and 0.3 CPU, then switch to a larger instance size. After adding your application, you can configure the environment variables it requires. For this example, only FLASK_SQLALCHEMY_ENGINES__default is needed. Since this variable holds your database URL, go to Networking and click Add internal connection. Select the database you created earlier, and then select Add environment variables to the application. Rename DB_URL to FLASK_SQLALCHEMY_ENGINES__default and click Add internal connection.
If you are using PostgreSQL, make sure the connection string starts with postgresql:// (not postgres://) so SQLAlchemy can connect properly.