Plantilla Acceso Libre 20 Feb, 2026

Template: Microservicio FastAPI + Docker

Estructura completa para un microservicio con FastAPI, SQLAlchemy, Alembic, Docker y tests con pytest. Listo para producción.

#fastapi #docker #microservicio #sqlalchemy #python

Contenido

Microservicio FastAPI + Docker

Template completo para levantar un microservicio con FastAPI, SQLAlchemy async, y Docker. Listo para desarrollo y producción.

Estructura del proyecto

service/
├── app/
│   ├── __init__.py
│   ├── main.py
│   ├── config.py
│   ├── database.py
│   ├── models.py
│   ├── schemas.py
│   ├── api/
│   │   └── v1/
│   │       ├── router.py
│   │       └── endpoints/
│   │           └── items.py
│   └── services/
│       └── item_service.py
├── tests/
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
└── alembic.ini

config.py

from pydantic_settings import BaseSettings
from functools import lru_cache

class Settings(BaseSettings):
    app_name: str = "Mi Servicio"
    debug: bool = False
    database_url: str = "postgresql+asyncpg://user:pass@db:5432/mydb"
    redis_url: str = "redis://redis:6379/0"
    secret_key: str = "cambiar-en-produccion"
    cors_origins: list[str] = ["http://localhost:3000"]

    model_config = {"env_file": ".env"}

@lru_cache
def get_settings():
    return Settings()

database.py (async)

from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
from sqlalchemy.orm import DeclarativeBase

from app.config import get_settings

engine = create_async_engine(get_settings().database_url, echo=get_settings().debug)
async_session = async_sessionmaker(engine, expire_on_commit=False)

class Base(DeclarativeBase):
    pass

async def get_db() -> AsyncSession:
    async with async_session() as session:
        try:
            yield session
            await session.commit()
        except Exception:
            await session.rollback()
            raise

Dockerfile (multi-stage)

FROM python:3.12-slim AS base
WORKDIR /app
RUN pip install --no-cache-dir --upgrade pip

FROM base AS deps
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

FROM deps AS production
COPY . .
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]

docker-compose.yml

services:
  api:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql+asyncpg://postgres:postgres@db:5432/mydb
      - REDIS_URL=redis://redis:6379/0
      - DEBUG=true
    volumes:
      - .:/app
    command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: mydb
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  pgdata:

main.py

from fastapi import FastAPI
from contextlib import asynccontextmanager
from app.config import get_settings
from app.database import engine, Base
from app.api.v1.router import api_router

@asynccontextmanager
async def lifespan(app: FastAPI):
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)
    yield
    await engine.dispose()

app = FastAPI(
    title=get_settings().app_name,
    lifespan=lifespan,
)
app.include_router(api_router, prefix="/api/v1")

Recurso Externo

Este recurso incluye un enlace externo. Regístrate para acceder.

Inicia Sesión para Acceder

Únete a la Comunidad

Regístrate gratis para descargar archivos, guardar recursos en favoritos, ganar XP y acceder a cursos y el foro de la comunidad.

¿Ya tienes cuenta? Inicia sesión

Erik Taveras

Autor

Erik Taveras

Recursos Relacionados