Вы написали приложение на FastAPI, все работает на локальном компьютере: uvicorn main:app запускается за секунду, а Swagger‑документация по адресу localhost:8000/docs доступна для проверки. Но локальный сервер — это еще не продакшен. Чтобы приложением могли пользоваться реальные люди, его нужно развернуть на сервере, доступном из интернета. В статье разбираем по шагам, как это сделать.
Важное пояснение: почему в инструкции разные языки
В этой статье вы встретите фрагменты кода на трёх разных «языках» — и это не случайность. Деплой — это не только написание логики приложения, но и подготовка среды, где эта логика будет работать. Поэтому в одной инструкции неизбежно смешиваются:
- Bash — команды для терминала Linux, которыми вы управляете сервером: устанавливаете пакеты, клонируете репозиторий, настраиваете автозапуск.
- Python — сам код вашего FastAPI‑приложения: настройки, роуты, middleware.
- Dockerfile — специальный формат инструкций для сборки контейнера: он говорит Docker, какой образ взять, какие файлы скопировать и какую команду запустить.
Ниже мы будем использовать каждый из них строго по назначению — так, как это делают в реальной разработке.
Шаг 1. Подготовьте приложение к продакшену
Прежде чем переносить код на сервер, наведите порядок в проекте. Это сэкономит время и нервы позже.
Файл зависимостей
Убедитесь, что все библиотеки зафиксированы в requirements.txt или, что еще лучше, — в pyproject.toml. На сервере вам предстоит установить ровно те же пакеты, что и локально. Если чего-то не хватает, приложение упадет с ошибкой импорта.
Команда для bash
pip freeze > requirements.txt
Или, если используете Poetry или pip-tools, — экспортируйте зависимости через соответствующую команду. Главное, чтобы файл был актуальным.
Переменные окружения
Никаких паролей, ключей и адресов баз данных в коде быть не должно. Все, что может меняться между окружениями, — в переменные окружения через .env-файл. В коде — читаем через pydantic-settings или python-dotenv:
Команда для python
from pydantic_settings import BaseSettings class Settings(BaseSettings): database_url: str secret_key: str debug: bool = False class Config: env_file = ".env" settings = Settings()
Сам .env-файл добавьте в .gitignore — он не должен попасть в репозиторий.
CORS
Если фронтенд будет обращаться к API из браузера, настройте CORS-заголовки. На продакшене не оставляйте allow_origins=[«*»] — укажите конкретные домены:
Команда для python
from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins=["https://your-frontend.com"], allow_methods=["GET", "POST", "PUT", "DELETE"], allow_headers=["*"], )
Шаг 2. Выберите сервер и настройте окружение
Для начала подойдет недорогой виртуальный сервер (VPS) — например, на Яндекс Cloud, Selectel или зарубежных провайдерах. Минимальная конфигурация: 1–2 vCPU, 1–2 ГБ RAM, 20 ГБ диска. Для учебного проекта или небольшого API этого достаточно.
После покупки сервера подключитесь к нему по SSH:
Команда для bash
ssh root@<IP-адрес-сервера>
Создайте отдельного пользователя. Работать от root — плохая практика. Создайте пользователя с правами sudo:
Команда для bash
adduser deployer usermod -aG sudo deployer
Установите Python и системные зависимости. В зависимости от дистрибутива:
Команда для bash
# Ubuntu / Debian apt update apt install python3 python3-pip python3-venv nginx -y
Перенесите код на сервер. Проще всего — через Git. Загрузите репозиторий и склонируйте его на сервер:
Команда для bash
git clone https://github.com/yourname/your-app.git cd your-app
Создайте виртуальное окружение и установите зависимости:
Команда для bash
python3 -m venv venv source venv/bin/activate pip install -r requirements.txt
Создайте .env-файл на сервере и заполните его реальными значениями — адресом базы данных, секретным ключом и другими настройками.
Шаг 3. Запустите приложение через Gunicorn
uvicorn — отличный сервер для разработки. Но в продакшене принято использовать связку Gunicorn + Uvicorn: Gunicorn управляет рабочими процессами, а Uvicorn работает как ASGI-воркер внутри каждого процесса.
Установите Gunicorn:
Команда для bash
pip install gunicorn
Запустите приложение:
Команда для bash
gunicorn main:app \ --workers 3 \ --worker-class uvicorn.workers.UvicornWorker \ --bind 127.0.0.1:8000
Здесь main — имя файла с объектом app, —workers 3 — количество рабочих процессов. Хороший ориентир: количество ядер × 2 + 1. Для одноядерного сервера — 3 воркера.
Проверьте, что приложение работает:
Команда для bash
curl http://127.0.0.1:8000/docs
Должен вернуться HTML-ответ. Но извне сервера приложение пока недоступно — Gunicorn слушает только 127.0.0.1. Это правильно: наружу его выставит Nginx.
Шаг 4. Настройте Nginx как обратный прокси
Nginx примет входящие HTTP-запросы и перенаправит их к Gunicorn. Дополнительно он возьмет на себя отдачу статических файлов, обработку HTTPS и ограничение размера запросов.
Создайте конфигурацию:
Команда для bash
nano /etc/nginx/sites-available/your-app
nginx
server {
listen 80;
server_name your-domain.com;
client_max_body_size 10M;
location / {
proxy_pass http://127.0.0.1:8000;
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;
}
}
Активируйте конфигурацию и перезапустите Nginx:
Команда для bash
ln -s /etc/nginx/sites-available/your-app /etc/nginx/sites-enabled/ nginx -t systemctl restart nginx
Если домен уже привязан к IP-адресу сервера, приложение станет доступно по адресу http://your-domain.com.
Шаг 5. Настройте HTTPS
Без HTTPS современные браузеры будут помечать сайт как небезопасный, а API — откажутся принимать запросы из браузерных приложений. Самый простой способ получить бесплатный сертификат — Let’s Encrypt.
Установите Certbot:
Команда для bash
apt install certbot python3-certbot-nginx -y
Получите сертификат:
Команда для bash
certbot --nginx -d your-domain.com
Certbot сам модифицирует конфигурацию Nginx, добавит HTTPS и настроит автоматическое продление. Проверьте, что все работает:
Команда для bash
curl https://your-domain.com/docs
Шаг 6. Настройте автозапуск через systemd
Если сервер перезагрузится, приложение должно запуститься автоматически. Для этого — systemd-сервис.
Создайте файл сервиса:
Команда для bash
nano /etc/systemd/system/your-app.service ini [Unit] Description=Your FastAPI App After=network.target [Service] User=deployer Group=deployer WorkingDirectory=/home/deployer/your-app EnvironmentFile=/home/deployer/your-app/.env ExecStart=/home/deployer/your-app/venv/bin/gunicorn main:app \ --workers 3 \ --worker-class uvicorn.workers.UvicornWorker \ --bind 127.0.0.1:8000 Restart=always RestartSec=5 [Install] WantedBy=multi-user.target
Включите и запустите сервис:
Команда для bash
systemctl daemon-reload systemctl enable your-app systemctl start your-app
Теперь приложение будет автоматически перезапускаться при падении и подниматься после перезагрузки сервера. Проверить статус:
Команда для bash
systemctl status your-app
Шаг 7. Docker — когда хочется переносимости
Если проект растет или вы планируете переезжать между серверами, имеет смысл упаковать приложение в Docker-контейнер. Один Dockerfile — и приложение запустится одинаково где угодно.
Минимальный Dockerfile:
FROM python:3.12-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["gunicorn", "main:app", \ "--workers", "3", \ "--worker-class", "uvicorn.workers.UvicornWorker", \ "--bind", "0.0.0.0:8000"]
Сборка и запуск:
Команда для bash
docker build -t your-app . docker run -d -p 8000:8000 --env-file .env your-app
Для управления несколькими контейнерами — API, база данных, Redis — используйте Docker Compose. Он описывается в одном файле docker-compose.yml и запускает все сервисы одной командой. Но для первого деплоя без Docker вполне можно обойтись — и описанный выше связки Gunicorn + Nginx + systemd хватит за глаза.
Шаг 8. Проверьте, что все работает
Сделайте контрольный запрос из браузера или через curl:
Команда для bash
curl https://your-domain.com/docs
Откройте документацию — если Swagger UI загружается, значит приложение живо и доступно. Попробуйте отправить пару тестовых запросов через саму документацию.
Проверьте логи на всякий случай:
Команда для bash
journalctl -u your-app -f
Если что-то сломается — именно здесь вы увидите ошибку.
Что в итоге получилось
Несколько шагов от локального uvicorn до полноценного продакшена:
- Код готов к деплою: зависимости зафиксированы, секреты — в переменных окружения.
- На сервере — Python, виртуальное окружение, установленные пакеты.
- Gunicorn запускает приложение и управляет процессами.
- Nginx принимает HTTP-запросы и проксирует их к Gunicorn.
- Let’s Encrypt обеспечивает HTTPS.
- systemd перезапускает приложение при сбоях и перезагрузках.
- По желанию — Docker для переносимости.
Это базовая схема. Дальше можно добавлять: CI/CD для автоматического деплоя по пушу в репозиторий, мониторинг через Prometheus и Grafana, логирование в единое хранилище, балансировщик нагрузки перед несколькими инстансами. Главное — не бояться. Первый деплой всегда кажется сложнее, чем есть на самом деле. Сервер не укусит, а откатить изменения можно в любой момент.
