- Home »

Как создать REST API с Flask на Ubuntu
Если разрабатываешь веб-сервисы или просто хочешь быстро поднять API для своего проекта, то Flask — это как раз то, что нужно. Эта статья покажет, как создать REST API с Flask на Ubuntu-сервере. Мы пройдём весь путь от установки зависимостей до деплоя готового решения. Никаких лишних абстракций — только конкретные команды, рабочие примеры и практические советы из реального опыта.
Как это работает: архитектура Flask API
Flask — это микрофреймворк для Python, который позволяет создавать веб-приложения с минимальными усилиями. В отличие от Django, Flask не навязывает структуру проекта и даёт полную свободу в выборе компонентов.
Основные компоненты Flask API:
- Flask-приложение — центральный объект, который обрабатывает HTTP-запросы
- Роуты — декораторы, которые связывают URL с функциями
- Blueprint — для организации больших приложений
- Middleware — для обработки запросов и ответов
- Сериализаторы — для работы с JSON
Пошаговая настройка окружения
Для начала нужен Ubuntu-сервер. Если у тебя его нет, можешь заказать VPS или использовать выделенный сервер для более серьёзных проектов.
Установка Python и зависимостей
# Обновляем систему
sudo apt update && sudo apt upgrade -y
# Устанавливаем Python и pip
sudo apt install python3 python3-pip python3-venv -y
# Устанавливаем дополнительные пакеты
sudo apt install build-essential libssl-dev libffi-dev python3-dev -y
# Проверяем версию Python
python3 --version
Создание виртуального окружения
# Создаём проект
mkdir flask-api && cd flask-api
# Создаём виртуальное окружение
python3 -m venv venv
# Активируем окружение
source venv/bin/activate
# Устанавливаем Flask и дополнительные пакеты
pip install flask flask-restful flask-cors gunicorn python-dotenv
Создание базового API
Создаём файл app.py
с простым REST API:
from flask import Flask, jsonify, request
from flask_restful import Api, Resource
from flask_cors import CORS
import os
from dotenv import load_dotenv
# Загружаем переменные окружения
load_dotenv()
app = Flask(__name__)
api = Api(app)
CORS(app) # Разрешаем CORS для всех доменов
# Простая база данных в памяти
users = [
{"id": 1, "name": "Alice", "email": "alice@example.com"},
{"id": 2, "name": "Bob", "email": "bob@example.com"}
]
class UserList(Resource):
def get(self):
return {"users": users}, 200
def post(self):
data = request.get_json()
if not data or 'name' not in data or 'email' not in data:
return {"error": "Missing required fields"}, 400
new_user = {
"id": len(users) + 1,
"name": data['name'],
"email": data['email']
}
users.append(new_user)
return new_user, 201
class User(Resource):
def get(self, user_id):
user = next((u for u in users if u['id'] == user_id), None)
if user:
return user, 200
return {"error": "User not found"}, 404
def put(self, user_id):
user = next((u for u in users if u['id'] == user_id), None)
if not user:
return {"error": "User not found"}, 404
data = request.get_json()
user.update(data)
return user, 200
def delete(self, user_id):
global users
users = [u for u in users if u['id'] != user_id]
return {"message": "User deleted"}, 200
# Регистрируем роуты
api.add_resource(UserList, '/api/users')
api.add_resource(User, '/api/users/')
@app.route('/health')
def health_check():
return jsonify({"status": "healthy"}), 200
if __name__ == '__main__':
port = int(os.getenv('PORT', 5000))
debug = os.getenv('DEBUG', 'False').lower() == 'true'
app.run(host='0.0.0.0', port=port, debug=debug)
Создание файла конфигурации
Создаём файл .env
для переменных окружения:
PORT=5000
DEBUG=True
SECRET_KEY=your-secret-key-here
DATABASE_URL=sqlite:///app.db
Тестирование API
Запускаем приложение:
# Активируем виртуальное окружение
source venv/bin/activate
# Запускаем Flask
python app.py
Тестируем API с помощью curl:
# Получаем список пользователей
curl -X GET http://localhost:5000/api/users
# Создаём нового пользователя
curl -X POST http://localhost:5000/api/users \
-H "Content-Type: application/json" \
-d '{"name": "Charlie", "email": "charlie@example.com"}'
# Получаем конкретного пользователя
curl -X GET http://localhost:5000/api/users/1
# Обновляем пользователя
curl -X PUT http://localhost:5000/api/users/1 \
-H "Content-Type: application/json" \
-d '{"name": "Alice Smith"}'
# Удаляем пользователя
curl -X DELETE http://localhost:5000/api/users/1
Добавление базы данных
Для серьёзных проектов понадобится настоящая база данных. Установим SQLite и SQLAlchemy:
pip install flask-sqlalchemy flask-migrate
Создаём файл models.py
:
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
db = SQLAlchemy()
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
def to_dict(self):
return {
'id': self.id,
'name': self.name,
'email': self.email,
'created_at': self.created_at.isoformat()
}
Обновляем app.py
для работы с базой данных:
from flask import Flask, jsonify, request
from flask_restful import Api, Resource
from flask_cors import CORS
from flask_migrate import Migrate
from models import db, User
import os
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'sqlite:///app.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
migrate = Migrate(app, db)
api = Api(app)
CORS(app)
class UserListResource(Resource):
def get(self):
users = User.query.all()
return {"users": [user.to_dict() for user in users]}, 200
def post(self):
data = request.get_json()
if not data or 'name' not in data or 'email' not in data:
return {"error": "Missing required fields"}, 400
# Проверяем, не существует ли пользователь с таким email
existing_user = User.query.filter_by(email=data['email']).first()
if existing_user:
return {"error": "User with this email already exists"}, 400
user = User(name=data['name'], email=data['email'])
db.session.add(user)
db.session.commit()
return user.to_dict(), 201
api.add_resource(UserListResource, '/api/users')
# Создаём таблицы при первом запуске
with app.app_context():
db.create_all()
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
Настройка production-окружения
Gunicorn как WSGI-сервер
Создаём файл gunicorn_config.py
:
import multiprocessing
bind = "0.0.0.0:5000"
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = "sync"
worker_connections = 1000
max_requests = 1000
max_requests_jitter = 50
preload_app = True
timeout = 120
keepalive = 2
Запускаем с Gunicorn:
gunicorn -c gunicorn_config.py app:app
Настройка Nginx как reverse proxy
# Устанавливаем Nginx
sudo apt install nginx -y
# Создаём конфигурацию
sudo nano /etc/nginx/sites-available/flask-api
Содержимое конфигурации Nginx:
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
location /health {
access_log off;
proxy_pass http://127.0.0.1:5000/health;
}
}
Активируем конфигурацию:
# Создаём символическую ссылку
sudo ln -s /etc/nginx/sites-available/flask-api /etc/nginx/sites-enabled/
# Тестируем конфигурацию
sudo nginx -t
# Перезапускаем Nginx
sudo systemctl restart nginx
Создание systemd-сервиса
Создаём файл /etc/systemd/system/flask-api.service
:
[Unit]
Description=Flask API Service
After=network.target
[Service]
Type=exec
User=www-data
Group=www-data
WorkingDirectory=/path/to/your/flask-api
Environment=PATH=/path/to/your/flask-api/venv/bin
ExecStart=/path/to/your/flask-api/venv/bin/gunicorn -c gunicorn_config.py app:app
ExecReload=/bin/kill -s HUP $MAINPID
Restart=always
[Install]
WantedBy=multi-user.target
Активируем сервис:
sudo systemctl daemon-reload
sudo systemctl enable flask-api
sudo systemctl start flask-api
sudo systemctl status flask-api
Сравнение с другими решениями
Фреймворк | Скорость разработки | Производительность | Сложность | Экосистема |
---|---|---|---|---|
Flask | Высокая | Средняя | Низкая | Богатая |
Django REST | Средняя | Средняя | Высокая | Очень богатая |
FastAPI | Высокая | Очень высокая | Средняя | Растущая |
Express.js | Высокая | Высокая | Низкая | Огромная |
Интересные факты и нестандартные применения
- Микросервисная архитектура: Flask отлично подходит для создания небольших, специализированных сервисов
- Обработка WebSocket: с Flask-SocketIO можно создавать real-time приложения
- Интеграция с Celery: для асинхронной обработки задач
- GraphQL support: через библиотеку Graphene можно создавать GraphQL API
- Автоматическая документация: Flask-RESTX генерирует Swagger документацию
Пример интеграции с Celery для фоновых задач
from celery import Celery
import os
def make_celery(app):
celery = Celery(
app.import_name,
backend=app.config['CELERY_RESULT_BACKEND'],
broker=app.config['CELERY_BROKER_URL']
)
celery.conf.update(app.config)
return celery
app.config.update(
CELERY_BROKER_URL='redis://localhost:6379/0',
CELERY_RESULT_BACKEND='redis://localhost:6379/0'
)
celery = make_celery(app)
@celery.task
def send_email(email, message):
# Логика отправки email
time.sleep(10) # Имитация долгой операции
return f"Email sent to {email}"
@api.route('/send-email', methods=['POST'])
def send_email_endpoint():
data = request.get_json()
task = send_email.delay(data['email'], data['message'])
return jsonify({"task_id": task.id}), 202
Мониторинг и логирование
Добавляем логирование в приложение:
import logging
from logging.handlers import RotatingFileHandler
if not app.debug:
file_handler = RotatingFileHandler('logs/app.log', maxBytes=10240, backupCount=10)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('Flask API startup')
Автоматизация развёртывания
Создаём простой скрипт для развёртывания deploy.sh
:
#!/bin/bash
# Останавливаем сервис
sudo systemctl stop flask-api
# Обновляем код
git pull origin main
# Активируем виртуальное окружение
source venv/bin/activate
# Устанавливаем зависимости
pip install -r requirements.txt
# Выполняем миграции
flask db upgrade
# Запускаем сервис
sudo systemctl start flask-api
# Проверяем статус
sudo systemctl status flask-api
Заключение и рекомендации
Flask — это отличный выбор для создания REST API, особенно если нужно что-то быстро поднять или создать специализированный микросервис. Он даёт полный контроль над архитектурой и не навязывает лишних абстракций.
Когда использовать Flask:
- Быстрое прототипирование API
- Микросервисная архитектура
- Когда нужен полный контроль над компонентами
- Небольшие и средние проекты
Когда лучше выбрать альтернативы:
- Большие корпоративные проекты → Django REST Framework
- Высокие требования к производительности → FastAPI
- Нужны готовые решения из коробки → Django
Для production-окружения обязательно используй Gunicorn + Nginx, настрой логирование и мониторинг. Если планируешь высокую нагрузку, рассмотри возможность использования Redis для кеширования и Celery для фоновых задач.
Полезные ссылки:
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.