FastAPI y Railway: Despliegue sin Complicaciones

Oscar Molinar
6 min readNov 24, 2023

--

Banner FastAPI & Railway

Rápido, sencillo y sin complicaciones. Estas son las tres palabras clave que todo desarrollador busca al momento de desplegar una aplicación web.

En esta ocasión, vamos a explorar dos poderosas herramientas: FastAPI y Railway. ¿El objetivo? Desplegar nuestra aplicación en línea de manera rápida y sin dolores de cabeza.

FastAPI por un lado, es un framework de desarrollo web rápido, moderno y fácil de usar. Su principal ventaja es la velocidad y su alto rendimiento. FastAPI se ha convertido en una opción popular entre los desarrolladores para crear APIs de manera muy rápida.

Por otro lado tenemos a Railway. Es una plataforma diseñada para simplificar el proceso de lanzamiendo de aplicaciones web. Con Railway no necesitas preocuparte por configurar servidores ni realizar tediosas tareas manuales. Su objetivo es hacer que el despliegue sea lo más sencillo posible.

Tanto FastAPI como Railway son herramientas innovadoras que agilizan el proceso desde la creación hasta el despliegue final de tu aplicación web. Durante este tutorial, exploraremos como preparar nuestro entorno, configurar nuestra aplicación e integrarla con Railway para lograr un despliegue sin complicaciones.

Preparación del entorno

¡Primero lo primero! crea un directorio para alojar la aplicación FastAPI. Posteriormente, crea un entorno virtual para el proyecto. Desde la terminal, dentro de la carpeta el proyecto, ejecuta el siguiente comando:

mkdir fastapi-railway
cd fastapi-railway

python -m venv env

Para activar el entorno virtual, ejecuta el siguiente comando:

.\env\Scripts\activate

Luego, debemos asegurarnos de tener las dependencias del proyecto instaladas. FastAPI requiere al menos la versión 3.8 de Python, por lo que si aún no tienes esta versión instalada, te recomiendo que la actualices.

Para este proyecto, necesitaremos los módulos fastapi, uvicorn, pydantic y SQLAlchemy.

pip install fastapi uvicorn pydantic SQLAlchemy

Ya tenemos nuestro entorno listo. Podemos pasar a la siguiente etapa. La creación de nuestra API.

Manos a la obra

Crearemos una aplicación sencilla para la gestión de libros. Podremos leer, insertar, actualizar y eliminar libros a nuestra base de datos. Nuestro proyecto tendrá la siguiente estructura.

app/
|-- env/
|-- database.db
|-- database.py
|-- models.py
|-- main.py
|-- requirements.txt
|-- .gitignore

Primero crearemos la configuración de la base de datos. Para este ejemplo utilizaremos SQLite. Es una biblioteca que implementa un motor de base de datos SQL pequeño y rápido y con todas las funciones.

#database.py

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

URL_DATABASE = 'sqlite:///database.db'

engine = create_engine(URL_DATABASE)

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

Dentro del archivo models.py definiremos el modelo de datos. Este modelo nos ayudará a trabajar de manera más eficiente con la base de datos. Utilizaremos el ORM que provee SQLAlchemy. Esto facilita la lectura y escritura de información a la base de datos.

#models.py

from sqlalchemy import Column, Integer, String
from database import Base

class Book(Base):
__tablename__ = 'books'

id = Column(Integer, primary_key=True, index=True)
title = Column(String(255), nullable=False)
author = Column(String(255), nullable=False)
year = Column(Integer, nullable=False)

Dentro del archivo main.py, utilizaremos pydantic para la especificación y validación de nuestro esquema de datos para los libros, definimos una dependencia (db_dependency) para poder acceder a la sesión de la base de datos y pueda ser utilizada en la rutas de la aplicación.

#main.py

from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
from pydantic import BaseModel
from typing import Annotated

import models
from database import engine, SessionLocal

class BookBase(BaseModel):
title: str
author: str
year: int

app = FastAPI()
models.Base.metadata.create_all(bind=engine)

def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()

db_dependency = Annotated[Session, Depends(get_db)]

@app.get("/")
async def root():
return {"message": "Gestor de libros"}

@app.get("/books")
async def get_books(db: db_dependency):
return db.query(models.Book).all()

@app.get("/books/{book_id}")
async def get_book(book_id: int, db: db_dependency):
return db.query(models.Book).filter(models.Book.id == book_id).first()

@app.post("/books", response_model=BookBase)
async def create_book(book: BookBase, db: db_dependency):
db_book = models.Book(**book.dict())
db.add(db_book)
db.commit()
return db_book

@app.delete("/books/{book_id}")
async def delete_book(book_id: int, db: db_dependency):
db.query(models.Book).filter(models.Book.id == book_id).delete()
db.commit()
return {"message": "Book deleted"}

@app.put("/books/{book_id}", response_model=BookBase)
async def update_book(book_id: int, book: BookBase, db: db_dependency):
db_book = db.query(models.Book).filter(models.Book.id == book_id).first()
db_book.title = book.title
db_book.author = book.author
db_book.year = book.year
db.commit()
return db_book

Para agregar las librerías que necesitamos para nuestro proyecto al archivo requirements.txt, podemos ejecutar el siguiente comando

pip freeze > requirements.txt

Prueba la aplicación ejecutando el comando:

uvicorn main:app --reload

¡Perfecto! Tenemos nuestra aplicación configurada y funcionando. Ahora es momento de mostrar nuestra creación al mundo entero. Para esto, accederemos al sitio web de Railway.

GitHub pieza fundamental

Para poder realizar los despliegues en Railway utilizaremos GitHub. Mediante GitHub, Railway realiza los despliegues de manera automática al detectar un push sobre la rama principal del repositorio. Por ende, necesitas crear un repositorio y subir el proyecto.

Desde el dashboard, creamos un nuevo proyecto y seleccionamos Deploy from GitHub repo (Implementar desde el repositorio de GitHub).

Seleccionamos el repositorio que creamos para nuestra aplicación y luego la opción Deploy Now (Desplegar ya). Esto empezará con el despliegue de nuestra aplicación con el últimos commit de nuestra rama principal. Esto puede tomar unos segundos. Al terminar el despliegue, veremos el siguiente panel:

Peeero no tan rápido. Aún no está pública nuestra aplicación. Necesitamos realizar unos cuantos ajutes.

Configuración de versión de Python

Por default, Railway utiliza la versión 3.8 de Python. Para este proyecto, estoy utilizando la versión 3.10, por ende, para poder cambiar la versión, necesitamos especificarlo mediante las variables de entorno en la sección de Variables dentro del panel

Documentación de Nixpacks: https://nixpacks.com/docs/providers/python

Iniciar implementaciones

Debemos definir nuestro comando para ejecutar el despliegue de nuestro código. Para esto, dentro de la sección Settings > Deploy coloca el siguiente comando

uvicorn main:app --host 0.0.0.0 --port $PORT

Dominio público

Es momento de generar un dominio para nuestra aplicación. En la sección Settings > Networking generaremos un dominio público.

Después de unos segundos, podremos acceder al dominio de nuestra aplicación y con la alineación correcta de los planetas, podremos ver nuestra aplicación en producción y pública.

¡Excelente! Nuestra aplicación está funcionando y lista para compartirla con tus amigos, equipo o cliente.

La combinación de estas tecnologías permite una rápida implementación, una documentación automática y una estructura robusta para manejar datos.

Espero que te sea útil. Si tienes alguna duda o sugerencia, no dudes en dejar tu comentario o ponerte en contacto. ¡Tu retroalimentación es valiosa!⭐

Link del repositorio: https://github.com/oscarenriqq/fastapi-railway

--

--

Oscar Molinar

Desarrollador de software • Me encanta compartir ideas • Fútbol • Libros https://www.oscarmolinar.dev