Cómo desplegar una función de Azure Functions con FastAPI y GitHub
Daniel J. Saldaña
- 2 de agosto de 2024
- Puntuación de feedback

En este post, te explicaré cómo crear y desplegar una función de Azure Functions manualmente utilizando FastAPI y cómo integrar el proceso de creación con un repositorio de código de GitHub.
Paso 1: Configuración inicial de Azure Functions
Crea una cuenta de Azure: Si no tienes una cuenta de Azure, puedes crear una en azure.com.
Instala las herramientas de Azure:
- Azure CLI: Instalación de Azure CLI
- Azure Functions Core Tools: Instalación de Azure Functions Core Tools
Paso 2: Crear una función de Azure Functions desde el portal de Azure
Inicia sesión en el Portal de Azure.
Crea un nuevo recurso de Azure Functions:
- Navega a “Crear un recurso” y busca “Function App”.
- Haz clic en “Crear”.
Configura la aplicación de funciones:
- Detalles del proyecto: Selecciona tu suscripción y crea un nuevo grupo de recursos si no tienes uno.
- Detalles de la instancia: Proporciona un nombre único para tu aplicación de funciones.
- Publicación: Selecciona “Código”.
- Pila de tiempo de ejecución: Selecciona “Python” y la versión que prefieras.
- Región: Selecciona la región más cercana a ti o la que prefieras.
Configuración del hosting:
- Selecciona un plan de hosting y configuración del almacenamiento.
- Configura las opciones de red si es necesario.
Configuración de supervisión:
- Configura Application Insights si deseas monitorear el rendimiento de tu función.
Configuración de implementación continua:
- Habilita la configuración de implementación continua para desplegar el código desde GitHub utilizando GitHub Actions.
Paso 3: Configurar la implementación continua desde GitHub
Configuración de GitHub:
- Cuenta de GitHub: Conecta tu cuenta de GitHub.
- Organización: Selecciona la organización.
- Repositorio: Selecciona el repositorio donde se encuentra tu código.
- Rama: Selecciona la rama desde la cual deseas desplegar.
Configuración del flujo de trabajo:
- Haz clic en el botón para obtener una vista previa del archivo de flujo de trabajo de GitHub Actions.
- Asegúrate de que el flujo de trabajo se vea correcto y luego confirma la configuración.
Configuración de autenticación:
- Autenticación básica: Puedes habilitar o deshabilitar la autenticación básica según tus necesidades.
Paso 4: Integrar FastAPI con Azure Functions
- Código de FastAPI: Asegúrate de que tu archivo
main.py
contenga el siguiente código:
import azure.functions as func
from typing import Any, List, Union, Optional
from fastapi import FastAPI, Bodyfrom fastapi.responses import JSONResponsefrom pydantic import BaseModel, Field
app = FastAPI()app.title = "API de Daniel J. Saldaña"app.version = "0.0.1"
class ExampleUpdateRequest(BaseModel): date: int
class Education(BaseModel): name: str description: Union[str, None] = None score: float = Field(description="Calificación obtenida", ge=0, le=10)
education = { "1": {"name": "Experto Universitario en Cloud Computing. Arquitecturas y Soluciones (AWS y Azure)", "description": "La Unir", "score": 9.0}, "2": {"name": "Experto Universitario en Devops & Cloud", "description": "La Unir", "score": 9.0},}
class Experience(BaseModel): name: str description: Union[str, None] = None time: Union[str, None] = None
experience = { "5": {"name": "Software Arquitect", "description": "Toma decisiones de diseño de alto nivel y dicta estándares técnicos 📋, incluyendo estándares de codificación de software, herramientas y plataformas. Dirijo el diseño y desarrollo de la arquitectura tecnológica de un sistema 🏗️, aplicación o plataforma. Para ello, me encargo de seleccionar el software adecuado para cada función, vigilar la implementación y coordinar la resolución de los problemas técnicos que puedan surgir, planificando técnicamente cada paso a seguir en la construcción de esa arquitectura 💬.", "time": "📆 2022 - Actualidad"}, "4": {"name": "Site Reliability Engineering", "description": "Automatización de tareas operativas, creación de pipeline 🚀, diseño level design para garantizar la disponibilidad de las aplicaciones 🏗️, explotación de métricas e identificar, diagnosticar y resolver los problemas de aplicaciones 🧪.", "time": "📆 2022 - 2022"}, "3": {"name": "DevOps Engineer", "description": "Desarrollo automatizaciones en la solución CI/CD interna 🔧. Cooperación con los equipos de Arquitectura en la fase de design thinking así como en las distintas fases de desarrollo de evolutivo 🗒️. Miembro del equipo de estrategia del Dominio de Ingeniera para definir nuevos procedimientos y modelos de trabajo ✍️.", "time": "📆 2020 - 2022"}, "2": {"name": "SysAdmin Linux", "description": "Resolución de incidencias 🔴, automatización de procedimientos, creación y configuración de máquinas virtuales 🖥️, gestión de todo la infraestructura interna de la organización 🧮.", "time": "📆 2020 - 2020"}, "1": {"name": "SysAdmin Linux/Windows", "description": "Intervenciones en máquinas físicas y virtuales y entornos de servidores compartidos ☁️, gestión en clusters de correo ✉️, implementación de reglas de seguridad 🔐.", "time": "📆 2016 - 2019"},}
class Certifications(BaseModel): id: Optional[int] = None name: str description: Union[str, None] = None provider: Union[str, None] = None validity: Union[str, None] = None
certifications = { "1": {"name": "Microsoft Certified: Azure Network Engineer Associate", "description": "Earning Azure Network Engineer Associate validates skills and subject matter expertise in planning, implementing, and maintaining Azure networking solutions, including hybrid networking, connectivity, routing, security, and private access to Azure services. Professionals in this role deploy networking solutions using Azure Portal and other methods, including PowerShell, Azure Command-Line Interface (CLI), and Azure Resource Manager templates (ARM templates).", "provider": "Microsoft", "validity": "📆 2023 - 2024"}, "2": {"name": "AWS Cloud Quest: Cloud Practitioner", "description": "Earners of this badge have demonstrated basic solution building knowledge using AWS services and have a fundamental understanding of AWS Cloud concepts. Badge earners have acquired hands-on experience with compute, networking, database and security services.", "provider": "AWS", "validity": "📆 Does not expire"},}
@app.get("/hello-world/{date}", tags=["Example"], response_model=dict)async def get_hello_world(date: int) -> dict: return {"message": f"Soy Goliat y tengo {date} años."}
@app.put("/hello-world/{date}", tags=["Example"], response_model=dict)async def update_hello_world(date: int, request: ExampleUpdateRequest) -> dict: return {"message": f"Hola {request.date}, bienvenido a mi API."}
@app.post("/hello-world", tags=["Example"], response_model=dict)async def create_hello_world(name: str = "Goliat") -> dict: return {"message": f"¡Hola {name}!"}
@app.get("/", tags=["Home"], response_model=dict)def get_index() -> dict: return JSONResponse(content="Bienvenidos a la API de Daniel J. Saldaña")
@app.get("/aboutme", tags=["About me"], response_model=dict)def get_aboutme() -> dict: return JSONResponse(content="Soy Cloud Arquitect🔥, con un background de DevOp,SRE,SysAdmin y especializado en provedores Cloud como AWS, Azure y GCP. Dispongo de un fuerte dominio de Arquitectura Cloud y Diseño de modelos de CI/CD. Vivo en Almería, España 🌍 tengo 30 años")
@app.get("/education", tags=["Education"], response_model=List[Education])async def get_education() -> List[Education]: return JSONResponse(content=education)
@app.get("/education/{id}", tags=["Education"], response_model=Education)async def get_education_by_id(id: str) -> Education: return JSONResponse(content=education[id])
@app.get("/experience", tags=["Experience"],response_model=List[Experience])async def get_experience() -> List[Experience]: return JSONResponse(content=experience)
@app.get("/experience/{id}", tags=["Experience"], response_model=Certifications)async def get_experience_by_id(id: str) -> Certifications: return JSONResponse(content=experience[id])
@app.get("/certifications", tags=["Certifications"], response_model=List[Certifications])async def get_certifications() -> List[Certifications]: return JSONResponse(content=certifications)
@app.get("/certifications/{id}", tags=["Certifications"], response_model=Certifications)async def get_education_by_id(id: str) -> Certifications: return JSONResponse(content=certifications[id])
@app.get("/certifications/", tags=["Certifications"], response_model=List[Certifications])async def get_certifications_provider(provider: str) -> List[Certifications]: result = [] for certification in certifications.values(): if certification["provider"] == provider: result.append(certification) return JSONResponse(content=result)
Archivo
function_app.py
: Crea un archivofunction_app.py
con el siguiente contenido:function_app.py import azure.functions as funcfrom WrapperFunction import app as fastapi_appapp = func.AsgiFunctionApp(app=fastapi_app, http_auth_level=func.AuthLevel.ANONYMOUS)Estructura de archivos: Asegúrate de que tu proyecto tenga la siguiente estructura de archivos:
.├── WrapperFunction│ └── __init__.py├── function_app.py├── host.json└── requirements.txtArchivo
host.json
: Asegúrate de que tu archivohost.json
tenga la siguiente configuración:host.json {"version": "2.0","extensions": {"http": {"routePrefix": ""}}}Archivo
requirements.txt
: Asegúrate de que tu archivorequirements.txt
incluya las dependencias necesarias:requirements.txt fastapiuvicorn[standard]pyJWTpython-decouplepydantic[email]gunicornazure-functions
Paso 5: Desplegar la función
Empuja el código a GitHub: Asegúrate de que todo tu código esté empujado a la rama seleccionada en GitHub.
Verifica la implementación: GitHub Actions se encargará de desplegar automáticamente tu aplicación de funciones en Azure cada vez que realices cambios en el repositorio. Puedes monitorear el progreso desde la pestaña de Actions en tu repositorio de GitHub.
Probar la función:
- URL de la API: API-DanielJSaldaña
- Documentación Swagger: DOCS-DanielJSaldaña
¡Y eso es todo! Ahora tienes una función de Azure Functions desplegada con FastAPI y GitHub Actions.