Упаковка для продакшена — Развёртывание на Railway

В этой главе вы узнаете, как применить фабричный паттерн, настроить продакшен-окружение и развернуть блог на Flask в продакшене с помощью Railway.


Шаблон фабрики приложений create_app()

До сих пор app.py создавался напрямуюapp = Flask(__name__), что достаточно для разработки, но есть несколько проблем:

  • Невозможно создать независимый экземпляр приложения во время тестирования
  • Невозможно переключаться между различными конфигурациями в зависимости от среды (разработка/тестирование/производство)
  • Инициализация расширений тесно связана с экземпляром приложения

Шаблон фабрики приложенийЭто решает эти проблемы: инкапсулировать создание приложения в функцию.

Пример

# Путь к файлу: app/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_migrate import Migrate
from config import Config

db = SQLAlchemy()
login_manager = LoginManager()
migrate = Migrate()

def create_app(config_class=Config):
    """Фабрика приложения: создаёт экземпляр приложения Flask на основе класса конфигурации"""
    app = Flask(__name__)
    app.config.from_object(config_class)

    # Инициализация расширений (сначала создайте экземпляр приложения, затем привяжите расширения к приложению)
    db.init_app(app)
    login_manager.init_app(app)
    migrate.init_app(app, db)

    login_manager.login_view = 'auth.login'
    login_manager.login_message = 'Пожалуйста, сначала войдите в систему, чтобы получить доступ.'

    # Регистрация Blueprint
    from app.blueprints.main import main_bp
    from app.blueprints.posts import posts_bp
    from app.blueprints.auth import auth_bp
    from app.blueprints.user import user_bp
    app.register_blueprint(main_bp)
    app.register_blueprint(posts_bp)
    app.register_blueprint(auth_bp)
    app.register_blueprint(user_bp)

    # user_loader должен быть определён после создания приложения
    from app.models import User
    @login_manager.user_loader
    def load_user(user_id):
        return User.query.get(int(user_id))

    return app

Файл конфигурации config.py

Пример

# Путь к файлу: config.py
import os
from dotenv import load_dotenv

# Загрузить переменные окружения из файла .env (только для среды разработки)
load_dotenv()

class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-secret-key')
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL', 'sqlite:///blog.db')
    SQLALCHEMY_TRACK_MODIFICATIONS = False

class DevelopmentConfig(Config):
    DEBUG = True

class ProductionConfig(Config):
    DEBUG = False

# Выбор конфигурации на основе переменных окружения
config_map = {
    'development': DevelopmentConfig,
    'production': ProductionConfig,
    'default': DevelopmentConfig
}

Новый входной файл wsgi.py

Пример

# Путь к файлу: wsgi.py
from app import create_app

app = create_app()

Теперь метод запуска становится:

(venv) $ flask --app wsgi run --debug      # 开发模式
(venv) $ gunicorn wsgi:app                  # 生产模式(Gunicorn)

Обратите внимание на порядок импорта: Blueprint и user_loader должны быть импортированы внутри create_app() (не в начале файла), иначе возникнут циклические импорты (Blueprint ссылается на models, models ссылается на db, а db на тот момент ещё не привязана к app).


Сгенерируйте requirements.txt и Procfile

(venv) $ pip freeze > requirements.txt

Убедитесь, что файл содержит ключевые зависимости: Flask, Flask-SQLAlchemy, Flask-Migrate, Flask-Login, Flask-WTF, Flask-Admin, gunicorn, python-dotenv.

Создайте в корневом каталоге проектаProcfile:

web: gunicorn wsgi:app

Отправьте проект на GitHub

$ git init
$ echo "venv/" > .gitignore
$ echo "__pycache__/" >> .gitignore
$ echo "*.pyc" >> .gitignore
$ echo "instance/" >> .gitignore
$ echo ".env" >> .gitignore
$ git add .
$ git commit -m "初始化 Flask 博客项目"
$ git branch -M main
$ git remote add origin https://github.com/你的用户名/flask-blog.git
$ git push -u origin main

Обязательно.envдобавьте.gitignoreФайл .env содержит конфиденциальную информацию, такую как SECRET_KEY. После коммита в GitHub его нельзя полностью удалить (история Git сохранит его).


Развёртывание на Railway

  1. Посетитеrailway.appи войдите через GitHub
  2. Новый проект → Развернуть из репозитория GitHub → выберите flask-blog
  3. Railway автоматически обнаруживает Procfile и определяет команду запуска Gunicorn
  4. Задайте переменные окружения в Variables.
  5. Нажмите Deploy

Настройка переменных окружения

Имя переменнойЗначениеОписание
SECRET_KEYСлучайно сгенерированная длинная строкаШифровать сессию и CSRF-токен
DATABASE_URLАвтоматически добавляется RailwayПродакшен-база данных (PostgreSQL от Railway)
FLASK_ENVproductionИдентификатор производственной среды

Быстро сгенерировать SECRET_KEY:

$ python -c "import secrets; print(secrets.token_urlsafe(50))"

После успешного развертывания вы получите ссылку видаhttps://flask-blog.up.railway.app。


Следующее направление обучения

Направление обученияКому это подходитРекомендуемая отправная точка
Flask REST APIСоздайте API для фронтенд-фреймворков (Vue3/React)Используйте jsonify вместо render_template для создания RESTful API
Flask + Vue3/React: разделение фронтенда и бэкендаХотите использовать Flask для бэкенда и Vue3/React для фронтендаFlask предоставляет JSON API, а фронтенд взаимодействует через fetch
PostgreSQLНужна база данных промышленного уровняЗаменить SQLite, установить psycopg2, изменить DATABASE_URL
Развертывание в DockerКонтейнеризованное развёртываниеНаписать Dockerfile и оркестрировать с помощью docker-compose
Другие расширения