Flask + PostgreSQL: микросервис с Docker

Микросервис — это небольшое приложение, выполняющее отдельную бизнес‑функцию. В отличие от монолита, микросервисы позволяют независимо развёртывать, масштабировать и сопровождать компоненты системы. В этом руководстве вы реализуете простой пользовательский микросервис на Flask, подключённый к PostgreSQL, и запустите его в Docker.
Важно: пример рассчитан на учебные и прототипные задачи. Для продакшена потребуется доработать безопасность, тестирование и наблюдаемость.
Архитектура микросервиса
Микросервисная архитектура разбивает большую систему на изолированные сервисы. Каждый сервис отвечает за «свою» бизнес‑функцию и может иметь собственную базу данных и окружение. Связь между сервисами обычно идёт по HTTP/REST, gRPC или через брокеры сообщений (RabbitMQ, Kafka).
Преимущества:
- независимое развёртывание;
- изоляция отказов;
- возможность выбирать технологии для каждого сервиса.
Ограничения:
- сложнее наблюдаемость и отладка;
- межсервисная коммуникация добавляет задержки;
- требования к управлению данными и транзакциям усложняются.
Настройка PostgreSQL (быстрый старт)
Если PostgreSQL у вас не установлен, выберите вариант: локальная установка, облачный сервис или удалённая база данных. В этом примере мы используем Render (бесплатный тариф) для быстрого развёртывания тестовой базы.
- Перейдите на сайт Render, зарегистрируйтесь и откройте панель инструментов (dashboard).
- На панели выберите сервис PostgreSQL.
- На странице параметров базы заполните поля. Выберите бесплатный тариф и нажмите Create database.
Скопируйте внешний URL базы данных из страницы настроек. Он понадобится для подключения через SQLAlchemy.
Примечание: для продакшен‑баз используйте защищённые учётные данные, TLS и белые списки IP, где возможно.
Создание микросервиса на Flask
Ниже — шаги для создания проекта, установки зависимостей и написания простого API для управления пользователями.
Создайте структуру проекта
В терминале выполните:
mkdir flask-microservice
cd flask-microserviceУстановите virtualenv и создайте виртуальное окружение:
pip install virtualenv
virtualenv venv
# Windows:
.\venv\Scripts\activate
# Unix/macOS:
source venv/bin/activateУстановите зависимости
Создайте файл requirements.txt в корне проекта и добавьте:
flask
psycopg2-binary
sqlalchemyУстановите пакеты:
pip install -r requirements.txtРеализация сервера Flask
Создайте файл service.py в корне проекта и добавьте код ниже. Комментарии оставлены для пояснений.
from flask import Flask, request, jsonify
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
import psycopg2
app = Flask(__name__)
# Замените URL на ваш внешний URL из Render или другой БД
engine = create_engine("postgresql+psycopg2://flask_service_fe0v_user:4785MhjfkdjfhjfjyUx67O2Nuzjchb2MQIP@dpg-chffjfjdkgfk54d6mb7860-a.oregon-postgres.render.com/flask_service_fe0v")
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
Base.metadata.create_all(engine)
print("Table 'users' created successfully.")
Session = sessionmaker(engine)
@app.route("/api/user", methods=["POST"])
def create_user():
data = request.get_json()
name = data["name"]
try:
session = Session()
new_user = User(name=name)
session.add(new_user)
session.commit()
return {"id": new_user.id, "name": new_user.name, "message": f"User {name} created."}, 201
except Exception as e:
print(f"The error '{e}' occurred.")
return {"error": "An error occurred while creating the user."}, 500
@app.route("/api/user", methods=["GET"])
def get_all_users():
try:
session = Session()
users = session.query(User).all()
if users:
result = []
for user in users:
result.append({"id": user.id, "name": user.name})
return jsonify(result)
else:
return jsonify({"error": f"Users not found."}), 404
except Exception as e:
print(f"The error '{e}' occurred.")
return {"error": "An error occurred while getting all users."}, 500
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0")Важно: замените URL подключения на свой, скопированный из Render. Неправильный формат строки подключения приводит к ошибкам при создании engine.
Тестирование локально
Запустите сервис в разработческом режиме:
flask --app service runОткройте Postman или curl для проверки endpoint’ов. Пример POST‑запроса для добавления пользователя:
- Метод: POST
- URL: http://localhost:5000/api/user
- Тело (JSON): { “name”: “Ivan” }
Ответ должен содержать id созданного пользователя или сообщение об ошибке.
Контейнеризация с Docker
Docker позволяет упаковать приложение и его зависимости в контейнер. Ниже — простой Dockerfile для нашего сервиса.
Создайте Dockerfile в корне проекта:
FROM python:3.9-alpine
WORKDIR /app
COPY requirements.txt ./
RUN pip install -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "./service.py"]Постройте образ и запустите контейнер:
docker build -t flask-microservice .
docker run -p 5000:5000 flask-microserviceКонтейнер откроет порт 5000. Доступ к сервису будет по http://localhost:5000.
Примечание: для продакшена используйте более устойчивую базу образов, multi‑stage сборку, non‑root пользователя и переменные окружения для секретов.
Практики безопасности и рекомендации
Важно выполнить следующие шаги перед развертыванием в продакшен:
- Храните секреты (пароли, строки подключения) в менеджере секретов или переменных окружения, а не в коде.
- Включите TLS/HTTPS для всех входящих соединений.
- Ограничьте доступ к базе данных через белые списки IP и сеть сервисов.
- Настройте журналы доступа и централизованную систему логирования.
- Добавьте мониторинг (метрики и алерты) и трассировку запросов (OpenTelemetry).
- Регулярно обновляйте зависимости и базовый образ Docker.
Когда микросервисы — не лучшее решение
Контрпримеры и ограничения:
- Небольшой проект с одной командой. Монофония проще и быстрее доставки.
- Сильно связанны́е данные и сложные транзакции, где распределённые транзакции дороже.
- Команда не готова к DevOps и наблюдаемости — риски операций.
Альтернативы:
- Модульный монолит: код остаётся внутри одного процесса, но разделён на модули с чёткими границами.
- Сервисная шина (SOA) в крупных корпоративных системах.
Принятие решения: эвристики и модели
Ментальные модели для выбора архитектуры:
- «Пара людей» — монолит; «несколько независимых команд» — микросервисы.
- Если фича меняется часто и сильно влияет на масштабирование — выделяйте в сервис.
- Если операции над данными требуют атомарности — предпочтите единое хранилище.
Матрица зрелости (уровни):
- Уровень 0 — монолит без автоматизации;
- Уровень 1 — модульный монолит, базовые тесты;
- Уровень 2 — разделение на сервисы, CI/CD, логирование;
- Уровень 3 — автоматическое масштабирование, распределённая трассировка, SLO/SLI.
Чеклисты по ролям
Backend‑разработчик:
- Настроить миграции схемы (Alembic или аналог).
- Не хранить секреты в репозитории.
- Покрыть критичные endpoint’ы тестами.
DevOps/Инфраструктура:
- Настроить CI/CD для билдов и деплоя.
- Настроить мониторинг и алерты.
- Управление секретами и ротация ключей.
QA/Тестирование:
- Написать интеграционные тесты с тестовой БД.
- Проверить сценарии отказа и восстановления.
Security:
- Провести сканирование зависимостей и статический анализ кода.
- Настроить политический контроль доступа (RBAC).
Критерии приёмки
- Сервис успешно создаёт и возвращает пользователей через API.
- Миграции запускаются без ошибок на тестовой базе.
- Сервис работает в контейнере и отвечает на запросы.
- Логи содержат достаточную информацию для отладки (без секретов).
Тестовые случаи и сценарии приёмки
- Успешное создание пользователя: POST /api/user c валидным именем — ожидается 201 и тело с id.
- Получение списка: GET /api/user — ожидается 200 и список пользователей.
- Негативный сценарий: GET на пустой БД — ожидается 404 с корректным сообщением.
- Неправильная строка подключения — сервис запускается и логирует ошибку подключения.
Отладка распространённых ошибок
- Ошибка при create_engine: проверьте формат строки подключения и установленные драйверы.
- Ошибка импорта psycopg2: убедитесь, что psycopg2-binary установлен и соответствует Python‑версии.
- Docker не стартует: проверьте логи контейнера через docker logs
.
Миграция и переход от монолита
Мини‑методология перехода:
- Идентифицируйте границы: выделяйте небольшие, слабо связанные функции.
- Экстрагируйте данные и API для выбранной области.
- Настройте независимый CI/CD и окружение.
- Постепенно перенаправляйте трафик и отключайте старые функции.
Совет: сначала выделяйте read‑heavy или высоконагруженные компоненты — эффект масштабирования виден быстрее.
Безопасность: конкретные шаги
- Используйте механизмы аутентификации и авторизации (OAuth2, JWT) для API.
- Ограничьте доступ к endpoint’ам по ролям.
- Включите TLS и проверку сертификатов при подключении к БД (require_ssl).
- Примените принципы минимально необходимых прав для учетных записей базы данных.
Краткий глоссарий (1 строка на термин)
- Микросервис — автономный компонент, решающий одну бизнес‑задачу.
- Монолит — приложение, упакованное и разворачиваемое как одно целое.
- SQLAlchemy — ORM для работы с SQL базами в Python.
- Psycopg2 — популярный PostgreSQL адаптер для Python.
Часто задаваемые вопросы
Нужно ли разделять базу данных для каждого микросервиса?
Не обязательно, но изоляция данных снижает связность. Выбор зависит от требований консистентности.
Как хранить секреты для Docker-контейнеров?
Используйте менеджеры секретов облачного провайдера или HashiCorp Vault, либо Docker Secrets / Kubernetes Secrets.
Подходит ли Flask для микросервисов в продакшене?
Да, но в проде обычно используют WSGI/ASGI серверы (gunicorn/uvicorn), переменные окружения и пул подключений.
Вывод
Микросервис на Flask и PostgreSQL — простой и понятный старт для изучения распределённых архитектур. Этот пример показывает базовую реализацию, тестирование и развёртывание в Docker. Прежде чем переходить к микросервисам, оцените сложность проекта, командные навыки и требования к операционной поддержке.
Краткая сводка:
- Разделяйте систему на сервисы по бизнес‑границам.
- Автоматизируйте тесты, сборку и деплой.
- Инвестируйте в безопасность, мониторинг и логирование.
Источники кода проекта доступны в репозитории на GitHub (ссылка в оригинале проекта).
Похожие материалы
Как использовать WhatsApp в браузере
Как заблокировать приложения в Windows 11
Отключить планшетный режим в Google Chrome
Как безопасно выключить Raspberry Pi
Сбросить прогресс просмотра на Netflix