Упаковка для продакшена — Развёртывание на Railway
В этой главе вы узнаете, как применить фабричный паттерн, настроить продакшен-окружение и развернуть блог на Flask в продакшене с помощью Railway.
Шаблон фабрики приложений create_app()
До сих пор app.py создавался напрямуюapp = Flask(__name__), что достаточно для разработки, но есть несколько проблем:
- Невозможно создать независимый экземпляр приложения во время тестирования
- Невозможно переключаться между различными конфигурациями в зависимости от среды (разработка/тестирование/производство)
- Инициализация расширений тесно связана с экземпляром приложения
Шаблон фабрики приложенийЭто решает эти проблемы: инкапсулировать создание приложения в функцию.
Пример
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
Пример
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
Пример
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
- Посетитеrailway.appи войдите через GitHub
- Новый проект → Развернуть из репозитория GitHub → выберите flask-blog
- Railway автоматически обнаруживает Procfile и определяет команду запуска Gunicorn
- Задайте переменные окружения в Variables.
- Нажмите Deploy
Настройка переменных окружения
| Имя переменной | Значение | Описание |
|---|---|---|
| SECRET_KEY | Случайно сгенерированная длинная строка | Шифровать сессию и CSRF-токен |
| DATABASE_URL | Автоматически добавляется Railway | Продакшен-база данных (PostgreSQL от Railway) |
| FLASK_ENV | production | Идентификатор производственной среды |
Быстро сгенерировать 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 |