- Home »

Создание FastAPI приложения с помощью Docker Compose — пошагово
Сегодня разберём, как собрать и развернуть FastAPI приложение с Docker Compose. Если вы настраиваете серверы и ищете готовые решения для быстрого деплоя Python-приложений, эта статья для вас. Мы пройдём весь путь от создания простого FastAPI сервиса до его контейнеризации и оркестрации через Docker Compose.
Почему именно FastAPI + Docker Compose? Потому что это одна из самых быстрых и удобных связок для создания современных API. FastAPI даёт нам автоматическую генерацию OpenAPI документации, высокую производительность и отличную типизацию. Docker Compose позволяет легко управлять многоконтейнерными приложениями и их зависимостями.
Мы разберём три ключевых вопроса: как это всё работает под капотом, как быстро настроить всё с нуля, и какие подводные камни ждут в продакшене. Плюс покажу несколько нестандартных способов использования и автоматизации.
Как это работает: архитектура решения
Docker Compose позволяет описать всю инфраструктуру приложения в одном YAML-файле. Для FastAPI приложения типичная архитектура включает:
- Контейнер с FastAPI приложением
- База данных (PostgreSQL/Redis)
- Reverse proxy (Nginx)
- Мониторинг и логирование
Каждый сервис изолирован в своём контейнере, но они могут общаться через внутренние Docker сети. Это даёт нам масштабируемость, воспроизводимость и простоту деплоя.
Пошаговая настройка с нуля
Начнём с создания простого FastAPI приложения. Создайте директорию проекта и следующую структуру:
fastapi-docker/
├── app/
│ ├── __init__.py
│ ├── main.py
│ └── requirements.txt
├── docker-compose.yml
├── Dockerfile
└── .env
Сначала создадим само приложение. В файле app/main.py
:
from fastapi import FastAPI
from fastapi.responses import JSONResponse
import asyncio
import os
app = FastAPI(title="FastAPI Docker Demo", version="1.0.0")
@app.get("/")
async def root():
return {"message": "Hello from FastAPI in Docker!"}
@app.get("/health")
async def health_check():
return JSONResponse(
content={"status": "healthy", "environment": os.getenv("ENVIRONMENT", "development")}
)
@app.get("/info")
async def app_info():
return {
"app_name": "FastAPI Docker Demo",
"version": "1.0.0",
"python_version": "3.11"
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Файл зависимостей app/requirements.txt
:
fastapi==0.104.1
uvicorn[standard]==0.24.0
python-multipart==0.0.6
pydantic==2.5.0
Теперь создадим Dockerfile
для нашего приложения:
FROM python:3.11-slim
WORKDIR /app
# Копируем файл зависимостей
COPY app/requirements.txt .
# Устанавливаем зависимости
RUN pip install --no-cache-dir -r requirements.txt
# Копируем код приложения
COPY app/ .
# Открываем порт
EXPOSE 8000
# Команда запуска
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
Создаём файл окружения .env
:
ENVIRONMENT=development
DATABASE_URL=postgresql://user:password@postgres:5432/fastapi_db
REDIS_URL=redis://redis:6379
И наконец, главный файл docker-compose.yml
:
version: '3.8'
services:
app:
build: .
ports:
- "8000:8000"
env_file:
- .env
depends_on:
- postgres
- redis
volumes:
- ./app:/app
restart: unless-stopped
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: fastapi_db
POSTGRES_USER: user
POSTGRES_PASSWORD: password
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- app
restart: unless-stopped
volumes:
postgres_data:
redis_data:
Для Nginx создадим простой конфиг nginx.conf
:
events {
worker_connections 1024;
}
http {
upstream app {
server app:8000;
}
server {
listen 80;
location / {
proxy_pass http://app;
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;
}
}
}
Запускаем всё одной командой:
docker-compose up -d
Проверяем статус сервисов:
docker-compose ps
docker-compose logs app
Практические кейсы и подводные камни
Рассмотрим типичные проблемы и их решения:
Проблема | Симптом | Решение |
---|---|---|
Медленный старт приложения | Долгое время отклика после docker-compose up | Добавить healthcheck в docker-compose.yml и использовать depends_on с condition |
Потеря данных при рестарте | БД пустая после пересоздания контейнеров | Обязательно использовать volumes для PostgreSQL |
Проблемы с сетью между контейнерами | Ошибки подключения к БД | Использовать service names вместо localhost в connection strings |
Большой размер образа | Долгая сборка и деплой | Использовать alpine образы и multi-stage builds |
Пример улучшенного Dockerfile с multi-stage build:
FROM python:3.11-slim as builder
WORKDIR /app
COPY app/requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY app/ .
ENV PATH=/root/.local/bin:$PATH
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Продвинутые возможности и автоматизация
Для продакшена добавим мониторинг и логирование. Расширенный docker-compose.yml
:
version: '3.8'
services:
app:
build: .
ports:
- "8000:8000"
env_file:
- .env
depends_on:
- postgres
- redis
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: fastapi_db
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d fastapi_db"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
command: redis-server --appendonly yes
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana_data:/var/lib/grafana
volumes:
postgres_data:
redis_data:
grafana_data:
Создадим скрипт для автоматического деплоя deploy.sh
:
#!/bin/bash
echo "Pulling latest changes..."
git pull origin main
echo "Building and starting services..."
docker-compose down
docker-compose build --no-cache
docker-compose up -d
echo "Waiting for services to be ready..."
sleep 30
echo "Running health checks..."
curl -f http://localhost:8000/health || exit 1
echo "Deployment completed successfully!"
Для автоматизации CI/CD можно использовать GitHub Actions. Создайте .github/workflows/deploy.yml
:
name: Deploy FastAPI App
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to server
uses: appleboy/ssh-action@v0.1.5
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /path/to/your/app
git pull origin main
docker-compose down
docker-compose up -d --build
Альтернативные решения и сравнение
Существует несколько альтернатив Docker Compose для оркестрации:
- Kubernetes — избыточен для простых приложений, но незаменим для больших кластеров
- Docker Swarm — проще K8s, но менее функционален
- Podman Compose — drop-in замена Docker Compose без демона
- Vagrant — для виртуализации на уровне ОС
Статистика показывает, что Docker Compose используется в 73% проектов для локальной разработки и 41% для продакшена (согласно Docker State of Application Development Report 2023).
Полезные команды для работы
# Запуск в фоновом режиме
docker-compose up -d
# Просмотр логов конкретного сервиса
docker-compose logs -f app
# Перезапуск отдельного сервиса
docker-compose restart app
# Выполнение команды в контейнере
docker-compose exec app bash
# Просмотр используемых ресурсов
docker-compose top
# Остановка и удаление всех контейнеров
docker-compose down -v
# Пересборка образов
docker-compose build --no-cache
# Масштабирование сервиса
docker-compose up -d --scale app=3
Интересные факты и нестандартные применения
Docker Compose можно использовать не только для веб-приложений. Несколько креативных применений:
- Тестирование — запуск тестовых сред с разными версиями зависимостей
- Данные — ETL пайплайны с Apache Airflow и FastAPI
- ML — развертывание ML моделей с Jupyter, MLflow и FastAPI
- Микросервисы — связка FastAPI + RabbitMQ + Celery для фоновых задач
Для машинного обучения можно добавить в docker-compose.yml
:
jupyter:
image: jupyter/tensorflow-notebook:latest
ports:
- "8888:8888"
volumes:
- ./notebooks:/home/jovyan/work
environment:
- JUPYTER_ENABLE_LAB=yes
mlflow:
image: python:3.11-slim
ports:
- "5000:5000"
command: |
bash -c "pip install mlflow && mlflow server --host 0.0.0.0 --port 5000"
volumes:
- mlflow_data:/mlflow
volumes:
mlflow_data:
Деплой на продакшен
Для продакшена рекомендую использовать VPS или выделенный сервер. Основные изменения для продакшена:
- Использование production-ready WSGI сервера (Gunicorn)
- Настройка SSL через Let’s Encrypt
- Логирование в centralized системы
- Бэкапы БД
- Мониторинг и алерты
Пример продакшен docker-compose.yml
:
version: '3.8'
services:
app:
build: .
environment:
- ENVIRONMENT=production
depends_on:
- postgres
- redis
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx-prod.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- app
restart: unless-stopped
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./backups:/backups
restart: unless-stopped
volumes:
postgres_data:
Заключение и рекомендации
Docker Compose + FastAPI — это мощная связка для создания современных API. Главные преимущества:
- Быстрый старт — от идеи до работающего приложения за минуты
- Воспроизводимость — одинаковое окружение на всех этапах
- Масштабируемость — легко добавлять новые сервисы
- Изоляция — каждый компонент в своём контейнере
Рекомендую использовать этот подход для:
- Прототипирования API
- Микросервисных архитектур
- Локальной разработки
- Небольших и средних продакшен приложений
Для крупных высоконагруженных проектов стоит рассмотреть переход на Kubernetes, но Docker Compose отлично покрывает 80% задач. Главное — не забывайте про бэкапы, мониторинг и security best practices.
Полезные ссылки:
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.