Ir al contenido

El medio de los artesanos de la web martes, 3 de noviembre de 2026

MailStudio
Herramientas

DevContainers: estandarizar el entorno de desarrollo de un equipo web

La especificación Development Containers permite describir todo el entorno de desarrollo de un proyecto web en un archivo versionado, para que cada miembro del equipo abra el mismo entorno con un clic. Esta guía detalla su puesta en marcha y sus límites.

«En mi máquina funciona» sigue siendo una de las frases más costosas de un equipo de
desarrollo web: versiones distintas de Node o PHP según el puesto, una extensión de editor
que falta, una variable de entorno olvidada. La especificación Development Containers,
impulsada en buena parte por Microsoft y ya implementada por varios proveedores de
herramientas, responde a este problema describiendo el entorno de desarrollo completo —
runtime, herramientas, extensiones, puertos — en un archivo versionado junto con el código.

El problema que resuelven los DevContainers

Un proyecto web suele depender de una lista precisa de requisitos: una versión de runtime
(Node, PHP, Python), herramientas de línea de comandos, a veces una base de datos local,
extensiones de editor compartidas para el linting o el formateo. Documentar esa lista en un
README funciona durante un tiempo, hasta que el documento se desvía de la
realidad. Las
herramientas de línea de comandos propias de cada proyecto
acaban variando de una máquina a otra sin que nadie lo note hasta que aparece un error difícil
de reproducir.

Un DevContainer traslada esa documentación de un texto que hay que leer a una configuración
que el editor ejecuta directamente: construye un contenedor, instala ahí las herramientas
previstas, abre la carpeta del proyecto y expone los puertos necesarios. La persona que se
incorpora al equipo ya no instala nada en su máquina anfitriona, aparte de Docker y su editor.

Anatomía de un devcontainer.json

La configuración vive en .devcontainer/devcontainer.json, en la raíz del
repositorio. Un ejemplo para un proyecto Node.js con PostgreSQL:

{
  "name": "app-web-node",
  "dockerComposeFile": "docker-compose.yml",
  "service": "app",
  "workspaceFolder": "/workspace",
  "features": {
    "ghcr.io/devcontainers/features/node:1": { "version": "22" }
  },
  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode"
      ],
      "settings": {
        "editor.formatOnSave": true
      }
    }
  },
  "forwardPorts": [3000, 5432],
  "postCreateCommand": "npm install"
}

Las «features» son piezas reutilizables que instalan un runtime o una herramienta (Node,
PHP, Docker-in-Docker, GitHub CLI) sin escribir un Dockerfile a mano. El bloque
customizations.vscode instala automáticamente las extensiones y los ajustes del
equipo, para que el linting y el formateo sean idénticos para todos desde el momento en que se
abre el proyecto.

Qué herramientas soportan la especificación

HerramientaSoporteNota
Visual Studio CodeNativo (extensión Dev Containers)Implementación de referencia original de la especificación
GitHub CodespacesNativoLee devcontainer.json directamente para aprovisionar la instancia en la nube
JetBrains (IntelliJ, PhpStorm, WebStorm)Nativo desde 2024Mismos archivos, sin conversión
CLI devcontainerNativoConstruye y ejecuta el contenedor fuera del editor, útil en CI
Docker Compose soloCompatible como complementoUn DevContainer puede apoyarse en un docker-compose.yml existente

Poner en marcha un DevContainer en un proyecto existente

En un proyecto que ya funciona con Docker Compose, la migración se resume en tres pasos:
añadir una carpeta .devcontainer, apuntarla al archivo compose existente en lugar
de escribir uno nuevo, y declarar los puertos y el comando posterior a la creación. Para un
equipo que alterna entre varias ramas con
varios worktrees de Git en paralelo,
cada worktree puede abrir su propio DevContainer aislado, con sus propios puertos y su propio
estado de base de datos, sin interferir con las demás copias de trabajo.

Los secretos nunca deben escribirse en devcontainer.json, que se versiona junto
con el resto del repositorio. Se pasan al contenedor a través de las variables de entorno del
anfitrión (un campo remoteEnv o containerEnv que apunta a una
variable no versionada), siguiendo la misma lógica que
gestionar bien las variables de entorno en desarrollo web.

Un entorno de desarrollo documentado en un archivo de texto se desvía con el tiempo; uno
descrito en una configuración ejecutada no puede divergir del proyecto que lo define.

Límites y trampas que conviene conocer

En macOS y Windows, el rendimiento de E/S de disco de un volumen Docker montado desde el
anfitrión sigue siendo notablemente más lento que en un sistema de archivos Linux nativo. Para
un proyecto Node.js con una carpeta node_modules voluminosa, preferir un volumen
Docker nombrado frente a un montaje directo de la carpeta anfitriona reduce claramente el
impacto en los tiempos de build y de recarga en caliente.

Las imágenes base cargadas de herramientas preinstaladas (varios gigabytes) ralentizan la
primera apertura del proyecto y la actualización de la imagen en CI. Es mejor partir de una
imagen mínima y añadir solo las features realmente utilizadas. Por último, un DevContainer
estandariza el entorno de desarrollo, no el de producción: ejecutar las mismas imágenes en CI
mantiene la coherencia de las pruebas, pero el despliegue sigue siendo un tema aparte, con sus
propias restricciones de tamaño y seguridad de imagen.

EnfoqueAlcanceReproducibilidad
README con instrucciones manualesSolo documentaciónBaja: se desvía con el tiempo
Docker Compose soloServicios y dependenciasBuena para servicios, muda sobre el editor y sus extensiones
VagrantMáquina virtual completaBuena, pero más pesada de aprovisionar que un contenedor
DevContainerRuntime, herramientas, editor, puertosAlta: un único archivo versionado pilota el editor

Usar el mismo DevContainer en integración continua

La especificación también incluye una interfaz de línea de comandos, devcontainer,
que construye y ejecuta el mismo contenedor fuera de cualquier editor. Un pipeline de CI puede
así ejecutar las pruebas en el entorno exacto que usa el equipo en local, sin mantener una
segunda definición de imagen en paralelo:

npm install -g @devcontainers/cli

devcontainer up --workspace-folder .
devcontainer exec --workspace-folder . -- npm test

Este enfoque elimina toda una clase de regresiones causadas por la desviación entre el
entorno de desarrollo y el de CI: una dependencia del sistema instalada a mano en la máquina de
un desarrollador, y luego olvidada en la imagen que usa el pipeline, deja de ser un problema en
cuanto ambos entornos comparten la misma definición. La ganancia es clara en un proyecto PHP
que depende de extensiones nativas concretas, o en un proyecto Node.js que incluye módulos
compilados: la versión de la biblioteca de sistema subyacente ya no varía según la máquina que
ejecute el build.

La contrapartida es un tiempo de arranque del pipeline algo mayor que el de una imagen de CI
reducida al mínimo para ejecutar pruebas, ya que el contenedor también incluye las herramientas
y extensiones pensadas para el editor. Para los proyectos donde ese coste pesa en la duración
total del pipeline, una imagen de CI derivada de la misma base pero sin las capas específicas
del editor sigue siendo una opción razonable, siempre que se regenere automáticamente con cada
cambio del Dockerfile de origen en lugar de mantenerse a mano.

Lo que hay que recordar

La especificación Development Containers traslada la configuración del entorno de
desarrollo de una documentación que hay que mantener a un archivo que el editor ejecuta
realmente. Ahora cuenta con soporte nativo en VS Code, los IDE de JetBrains y GitHub
Codespaces, lo que la convierte en un estándar realista y no en una solución propietaria. Su
principal límite sigue siendo el rendimiento de E/S de disco en macOS y Windows, mejor resuelto
con volúmenes nombrados que con montajes directos de la carpeta anfitriona.

En los proyectos que retoma para clientes, el autor observa casi siempre el mismo
escenario: un README de instalación fechado hace varios meses, ya equivocado en al menos un
punto. Un DevContainer no lo resuelve todo, pero traslada la carga de la documentación a una
configuración que el editor comprueba cada vez que se abre el proyecto, lo que en la práctica
ahorra bastante ida y vuelta de depuración el primer día de un nuevo contrato —
Simon Janvier.

Para profundizar: la especificación completa en
containers.dev.

Compartir LinkedIn Bluesky Hacker News E-mail

Leer también