Deja de Contaminar Tu Máquina: Por Qué los Devcontainers Son el Camino a Seguir
Cómo los devcontainers eliminan la deriva de entornos, mantienen los proyectos aislados y hacen que los flujos de trabajo multi-cuenta de AWS sean sin complicaciones.

Deja de Contaminar Tu Máquina: Por Qué los Devcontainers Son el Futuro
Todo desarrollador ha estado ahí. Clonas un repositorio, sigues el README, y pasas las próximas dos horas depurando por qué Node 18 está peleando con Node 20, por qué tus paquetes globales de Python están filtrándose a un virtualenv, o por qué aws sts get-caller-identity está devolviendo la cuenta incorrecta. Tu laptop se ha convertido en un cementerio de cadenas de herramientas en conflicto, y no recuerdas qué proyecto necesita qué.
Los devcontainers resuelven todo esto.
¿Qué Es un Devcontainer?
Un devcontainer es un entorno de desarrollo completo definido como código — un contenedor Docker (o un conjunto de contenedores via Docker Compose) que tu editor arranca y al que se conecta automáticamente. VS Code, JetBrains y GitHub Codespaces todos lo soportan de forma nativa. Abres el proyecto, el editor lee .devcontainer/devcontainer.json, construye la imagen, y te deja en una terminal que tiene exactamente las herramientas, tiempos de ejecución y configuración que ese proyecto necesita.
Nada más. Nada menos.
Por Qué los Devcontainers Superan al Desarrollo Local
1. Aislamiento Real Entre Proyectos
Cuando cada proyecto corre dentro de su propio contenedor, no hay contaminación cruzada. El Proyecto A puede usar Node 18, Python 3.10 y Terraform 1.5. El Proyecto B puede usar Node 22, Python 3.12 y Terraform 1.8. Nunca interfieren entre sí porque literalmente no pueden verse.
Se acabó el nvm use, el pyenv local, el "en mi máquina funciona."
"¿Pero No Puedo Simplemente Usar Docker Compose Para Eso?"
Probablemente estés pensando: Ya corro mi app en Docker Compose. Es lo mismo, ¿no? Para nada.
Docker Compose simple te da servicios en contenedores, no un entorno de desarrollo en contenedor. Cuando usas Compose sin un devcontainer, típicamente editas código en tu host y lo montas en un contenedor que corre tu app. En el momento en que necesitas instalar una nueva dependencia, cambiar una librería del sistema o depurar algo, o bien entras al contenedor con docker exec — perdiendo tu editor, extensiones, depurador y configuración de git — o reconstruyes toda la imagen.
Y reconstruir es donde empieza el dolor. La caché de capas de Docker es agresiva y opaca. Añades una nueva línea apt-get install y la caché te sirve una capa obsoleta porque la instrucción RUN anterior no cambió. Haces pip install de un nuevo paquete pero la capa en caché todavía tiene el requirements.txt viejo integrado. Pierdes 20 minutos antes de darte cuenta de que necesitas --no-cache, que entonces reconstruye todo desde cero, incluyendo las capas que estaban bien. Es una muerte por mil invocaciones de docker build.
Los devcontainers resuelven esto porque tu editor está dentro del contenedor. VS Code (o JetBrains) se conecta directamente al entorno en ejecución. Tus extensiones, tu depurador, tu terminal, tu IntelliSense — todo corre contra el sistema de archivos y la cadena de herramientas del contenedor. No estás entrando desde afuera; estás trabajando desde adentro. ¿Necesitas instalar algo? Ejecútalo en la terminal integrada. Persiste en la capa de escritura del contenedor hasta que reconstruyas, y cuando sí reconstruyes, los hooks del ciclo de vida de devcontainer.json (postCreateCommand, postStartCommand) se encargan de volver a ejecutar tus pasos de configuración automáticamente.
La diferencia es sutil pero enorme: Docker Compose te da tiempo de ejecución aislado. Los devcontainers te dan un espacio de trabajo aislado.
2. Incorporación en Minutos, No Días
Un nuevo compañero clona el repositorio, lo abre en VS Code, hace clic en "Reopen in Container" y listo. El Dockerfile y el archivo docker-compose son las instrucciones de configuración. No hay ninguna página de Confluence de 47 pasos que seguir. No hay conocimiento tribal sobre qué fórmula de Homebrew instalar. El entorno se inicializa solo.
3. Reproducible En Todo el Equipo
Todos ejecutan el mismo sistema operativo, las mismas versiones de paquetes, las mismas librerías del sistema. Si funciona en el contenedor, funciona para todos. El CI/CD puede usar el mismo Dockerfile, por lo que reduces aún más la brecha entre el desarrollo local y producción.
4. Tu Máquina Host Se Mantiene Limpia
Tu laptop es para navegar, correo electrónico y ejecutar Docker. Eso es todo. Nunca más instalas herramientas específicas de un proyecto en tu host. Cuando terminas con un proyecto, eliminas el contenedor. No hay nada que desinstalar.
El Verdadero Movimiento Poderoso: Credenciales AWS Por Proyecto con SSO
Aquí es donde los devcontainers pasan de "agradable tenerlos" a "no puedo volver atrás." Si tu organización usa AWS SSO (IAM Identity Center) con múltiples cuentas — y debería — probablemente hayas lidiado con el dolor de cambiar perfiles. Ejecutas aws sso login --profile staging, luego olvidas pasar --profile staging en tu siguiente llamada CLI, y de repente estás mirando recursos de producción preguntándote por qué tus datos se ven diferentes.
Los devcontainers eliminan esto por completo.
Cómo Funciona
El patrón es simple:
- Configura los perfiles AWS SSO en tu máquina host. Cada perfil mapea a una cuenta AWS y rol específicos via
~/.aws/config. - Monta
~/.awsdentro del contenedor. Esto le da al contenedor acceso a tus tokens de sesión SSO sin duplicar credenciales. - Establece
AWS_PROFILEcomo variable de entorno en el contenedor. Cada llamada AWS CLI, cada inicialización de SDK, cada plan de Terraform dentro de ese contenedor usará automáticamente el perfil correcto, sin necesidad de la flag--profile.
Esto significa que el devcontainer de cada proyecto está fijado a su cuenta AWS. Literalmente no puedes ejecutar accidentalmente un comando contra la cuenta incorrecta porque el entorno no te lo permite.
Ejemplo: ~/.aws/config en Tu Host
[profile nebustream-dev]
sso_session = nebustream
sso_account_id = 111111111111
sso_role_name = DeveloperAccess
region = us-east-1
[profile nebustream-staging]
sso_session = nebustream
sso_account_id = 222222222222
sso_role_name = DeveloperAccess
region = us-east-1
[profile nebustream-prod]
sso_session = nebustream
sso_account_id = 333333333333
sso_role_name = ReadOnlyAccess
region = us-east-1
[sso-session nebustream]
sso_start_url = https://yourawsstarturl.awsapps.com/start
sso_region = us-east-1
sso_registration_scopes = sso:account:access
Cada perfil apunta a una cuenta AWS diferente. El bloque sso-session maneja el flujo de inicio de sesión compartido para que solo te autentiques una vez.
Ejemplo: docker-compose.yml
Aquí hay una configuración real de devcontainer. Nota el AWS_PROFILE y el montaje del volumen ~/.aws — ese es todo el truco.
services:
devcontainer:
container_name: devcontainer
build:
context: ..
dockerfile: .devcontainer/Dockerfile
args:
NEBUSTREAM_EMAIL: ${NEBUSTREAM_EMAIL}
NEBUSTREAM_USERNAME: ${NEBUSTREAM_USERNAME}
command: ["sh", "-c", "tail -f /dev/null"]
volumes:
- ..:/workspace:cached
- ~/.aws:/root/.aws # Monta la configuración AWS + caché SSO del host
- /var/run/docker.sock:/var/run/docker.sock
environment:
- AWS_PROFILE=nebustream-dev # Bloqueado a esta cuenta
- NODE_ENV=local
- AWS_DEFAULT_REGION=us-east-1
ports:
- "3000:3000"
- "5173:5173"
networks:
- localstack-net
nginx:
image: nginx:stable
container_name: nginx
depends_on:
- superset
- limesurvey
- pgadmin
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
networks:
- localstack-net
superset:
build:
context: .
dockerfile: ./Dockerfile.superset
args:
COGNITO_CLIENT_ID: ${COGNITO_CLIENT_ID}
COGNITO_CLIENT_SECRET: ${COGNITO_CLIENT_SECRET}
ports:
- "8088:8088"
depends_on:
- postgres-superset
networks:
- localstack-net
postgres:
image: postgres:17.2
environment:
- POSTGRES_USER=admin
- POSTGRES_PASSWORD=admin
- POSTGRES_DB=cadash_db
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
networks:
- localstack-net
pgadmin:
image: dpage/pgadmin4:9.10.0
environment:
- PGADMIN_DEFAULT_EMAIL=admin@admin.com
- PGADMIN_DEFAULT_PASSWORD=admin
ports:
- "5050:80"
volumes:
- pgadmin_data:/var/lib/pgadmin
depends_on:
- postgres
networks:
- localstack-net
networks:
localstack-net:
driver: bridge
volumes:
pgadmin_data:
pgdata:
Las dos líneas que más importan:
volumes:
- ~/.aws:/root/.aws
environment:
- AWS_PROFILE=nebustream-dev
Eso es todo. Cada llamada aws CLI, cada sesión de Boto3, cada despliegue de CDK dentro de este contenedor ahora apunta a nebustream-dev automáticamente. Sin flags. Sin errores. Sin "ay no, eso era producción."
Cómo Se Ve En La Práctica
Una vez dentro del contenedor, AWS simplemente funciona:
# No se necesita la flag --profile. Nunca.
aws sts get-caller-identity
# → Account: 111111111111, Role: DeveloperAccess
aws s3 ls
# → Lista los buckets solo en la cuenta de desarrollo
aws lambda list-functions
# → Solo las lambdas de desarrollo
npx cdk deploy
# → Despliega en dev. Siempre.
Si necesitas trabajar en el proyecto de staging, abres el devcontainer de ese repositorio, que tiene AWS_PROFILE=nebustream-staging. No cambias perfiles — cambias de proyecto. El entorno sigue al código.
Manejo del Inicio de Sesión SSO
Lo único que todavía haces en tu máquina host es el inicio de sesión SSO inicial:
# Ejecuta esto en tu host (no dentro del contenedor)
aws sso login --profile nebustream-dev
Como ~/.aws está montado en el contenedor, la caché de tokens SSO es compartida. El contenedor recoge la sesión activa inmediatamente. La mayoría de las sesiones SSO duran entre 8 y 12 horas, así que típicamente inicias sesión una vez al comenzar tu día.
Consejo: Si tu sesión SSO expira mientras trabajas, verás un error
ExpiredTokendentro del contenedor. Solo ejecutaaws sso loginen tu host nuevamente — el contenedor recogerá el token actualizado automáticamente ya que el directorio está montado.
Yendo Más Lejos: Un Stack Completo en una Caja
El ejemplo anterior no es solo un devcontainer — es un stack local completo. Postgres, pgAdmin, Nginx, Superset, todos conectados en una red Docker compartida. Esto significa:
- Los desarrolladores de backend pueden probar endpoints de API contra una base de datos real sin instalar Postgres localmente.
- Los desarrolladores de frontend pueden ejecutar la app en el puerto 3000 y llamar a la API local a través de Nginx, igual que en producción.
- Los ingenieros de datos pueden consultar paneles de Superset localmente con el mismo flujo de autenticación de Cognito.
Todos obtienen el mismo stack. El entorno de todos está definido en el mismo docker-compose.yml. Nadie depura un problema de "en mi Postgres 14 funciona pero tú estás corriendo 17."
La Mentalidad del Devcontainer
Adoptar devcontainers no es solo un cambio de herramientas — es un cambio de mentalidad. Dejas de pensar en tu laptop como un entorno de desarrollo y empiezas a pensar en él como un host para entornos de desarrollo. Cada proyecto lleva su propio mundo consigo. Cuando abres el proyecto, el mundo se activa. Cuando lo cierras, el mundo desaparece.
Tu máquina se mantiene limpia. Tus cuentas AWS permanecen seguras. Tus compañeros siguen siendo productivos.
Si todavía no has probado los devcontainers, empieza con un proyecto. Añade una carpeta .devcontainer, escribe un Dockerfile, establece tu AWS_PROFILE, y nunca mires atrás.