Antes de dockerizar, hay dos ajustes que se deben hacer al código.
Un contenedor no sabe nada de tu máquina local. La conexión a la base de datos debe llegar desde afuera, no estar escrita en el código.
# antes
DATABASE_URL = "postgresql://neondb_owner:abc123@host-remoto/neondb"
# después
import os
DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://user:password@localhost/neondb")- Docker Desktop instalado y corriendo
FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY main.py .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]--host 0.0.0.0 es obligatorio. Sin esto uvicorn solo escucha dentro del contenedor > y no es accesible desde el host.
Ejecutar desde la raíz del proyecto (donde están Dockerfile y main.py)
docker build -t fastapi-iot .docker images lsPor defecto docker build construye para la arquitectura de tu máquina (ej. arm64 en Apple Silicon). Para publicar una imagen que funcione en amd64 (servidores Linux) y arm64 simultáneamente
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t fastapi-iot \
.docker network create iot-networkdocker run -d --name db -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=iotdb postgres:17docker network connect iot-network dbdocker run -d --name api -p 8000:8000 --network iot-network -e DATABASE_URL=postgresql://postgres:postgres@db:5432/iotdb fastapiiotdocker network inspect iot-networkLos contenedores vienen limpios, sin toda la paquetería de un sistema operativo. Esto lo vamos a hacer por diversión, vamos a instalar las herramientas de IP al contenedor para poder hacer ping
apt update
apt install iputils-pingLuego entremos al contenedor
docker exec -it api shFinalmente, hagamos ping
ping dbEl archivo docker-compose.yml define dos servicios en la misma red:
┌─────────────────────────────────────┐
│ red: docker_default │
│ │
│ ┌──────────┐ ┌─────────────┐ │
│ │ api │─────▶│ db │ │
│ │ :8000 │ │ postgres:17 │ │
│ └──────────┘ └─────────────┘ │
└─────────────────────────────────────┘
El servicio api se conecta a db usando el hostname db — Docker Compose registra
cada servicio como hostname en la red interna:
environment:
- DATABASE_URL=postgresql://postgres:postgres@db:5432/iotdb
# ^^^
# hostname del servicio postgresdepends_on hace que api arranque después de que el contenedor db esté corriendo:
depends_on:
- dbDesde la raíz del proyecto:
docker compose up --build--build fuerza reconstruir la imagen de api. Para correr en background:
docker compose up --build -dPara detener y eliminar los contenedores:
docker compose downDocker Compose crea automáticamente una red llamada <carpeta>_default.
docker network lsSalida esperada (entre otras):
NETWORK ID NAME DRIVER SCOPE
83d8498846d8 docker_default bridge local
docker network inspect docker_defaultEn la sección Containers verán los dos contenedores con sus IPs asignadas dentro
de la red interna (ej. 172.18.0.2, 172.18.0.3).
docker inspect docker-api-1Buscar NetworkSettings.Networks para ver la IP, gateway y redes a las que pertenece.
# Entrar al contenedor api
docker exec -it docker-api-1 sh
# Dentro del contenedor, resolver el hostname "db"
cat /etc/hosts# Health check
curl http://localhost:8000/
# Guardar una lectura (persiste en PostgreSQL)
curl -X POST http://localhost:8000/readings \
-H "Content-Type: application/json" \
-d '{"value":100,"timestamp":1234,"deviceName":"Sensor01","unit":"celsius"}'Primero asegurese de estar logeado en docker. Puede hacerlo en la versión de escritorio gráficamente o mendiante el comando
docker login
Luego, debe saber su nombre de usuario, para el ejemplo domic0620 y el nombre de la imagen es api
docker tag api domic0620/integradorapi:0.0.1
Y luego lo puede subir al registry DockerHub
docker push domic0620/integradorapi:0.0.1