Docker Desktop vs Docker en WSL: ¿Cuál es realmente más rápido?

¿Te fue útil?

Si tus contenedores se sienten como si corrieran sobre cemento mojado en Windows, no lo estás imaginando. La brecha de rendimiento entre “Docker Desktop” y “Docker en WSL” es real, pero también se entiende mal. La mayoría de la gente mide lo incorrecto y luego lo “arregla” complicando su configuración y dificultando la depuración.

Te voy a decir qué es lo que realmente es más rápido, por qué, y cómo probarlo en tu máquina en menos de una hora —sin aplicar configuraciones por imitación que no recordarás el próximo trimestre.

Qué estás comparando realmente (y por qué los nombres engañan)

En Windows, “Docker” como producto y “Docker” como motor se enredan. La gente dice “Docker Desktop es lento” cuando quiere decir “mis bind mounts son lentos”. O dicen “Docker en WSL es más rápido” cuando por accidente movieron su código fuente a un sistema de archivos Linux y dejaron de pagar el impuesto del sistema de archivos de Windows.

Definamos las dos configuraciones en la forma en que el rendimiento realmente importa:

  • Docker Desktop: una aplicación de Windows que ejecuta el Docker Engine dentro de una VM Linux. En versiones modernas, esa VM suele estar respaldada por WSL2. Desktop también añade integraciones: interfaz gráfica, ayudantes de credenciales, pegamento de red, rutas de compartición de archivos, extensiones y controles de políticas.
  • Docker Engine dentro de WSL2 (“Docker en WSL”): instalas y ejecutas el Docker Engine de Linux directamente en tu distribución WSL. No hace falta la app Desktop. Los contenedores se ejecutan en el mismo entorno VM de WSL2, pero gestionas el demonio como en un sistema Linux normal.

Fíjate en lo que falta: el runtime de contenedores no cambia mágicamente. Ambos acaban en un contexto de kernel Linux (la VM de WSL2). La diferencia es dónde vive tu demonio, cómo está cableado el intercambio de archivos y cuántas capas de traducción añades por accidente.

Aquí tienes la forma más rápida de pensarlo:

  • Si tu carga está limitada por CPU (compilaciones, compresión, crypto), Desktop vs WSL Engine suele ser una diferencia menor.
  • Si tu carga está limitada por el sistema de archivos (instalaciones de Node.js, recargas en caliente, servidores de lenguaje, grandes monorepos), la ubicación de los archivos y el tipo de montaje lo dominan todo.
  • Si tu carga está limitada por la red (muchos servicios en localhost, proxies, VPN), detalles de integración y rutas NAT pueden hacer que uno parezca “aleatoriamente” peor.

Una cita, porque encaja: Werner Vogels tiene una idea parafraseada de que todo falla, todo el tiempo —así que diseñas y operas asumiendo fallos. El trabajo de rendimiento es similar: asume que tu camino más rápido se degradará a menos que lo mantengas simple y observable.

Broma #1: Hacer benchmarks de Docker en Windows sin comprobar dónde vive tu código es como cronometrar un coche deportivo con el freno de mano puesto. Obtendrás un número, claro.

Algunos hechos e historial que puedes usar en discusiones

Esto no son datos para trivialidades. Explican por qué el perfil de rendimiento se ve como se ve.

  1. Docker en Windows inicialmente dependía mucho de Hyper-V para ejecutar una VM Linux, porque los contenedores necesitan un kernel Linux. Las configuraciones tempranas tenían una sobrecarga notable y una red frágil.
  2. WSL1 no era una VM; traducía llamadas al sistema Linux en comportamiento de Windows. Fue ingenioso, pero no era “Linux real”, y muchos comportamientos de contenedores eran incómodos o imposibles.
  3. WSL2 cambió a un kernel Linux real en una VM ligera, lo que hizo que las cargas de trabajo de contenedores Linux fueran mucho más compatibles—y a menudo más rápidas para operaciones nativas de sistema de archivos Linux.
  4. Los problemas de rendimiento de archivos a menudo vienen de cruzar la frontera Windows/Linux (por ejemplo, acceder a /mnt/c desde Linux). Esa frontera debe traducir metadatos, permisos y semánticas de notificación.
  5. Los bind mounts no son inherentemente lentos; los bind mounts que atraviesan una frontera de virtualización sí lo son. Un bind mount de Linux dentro del sistema de archivos Linux suele estar bien.
  6. Docker Desktop ha evolucionado hacia una plataforma, no solo un lanzador de demonio. Las características extra son útiles, pero añaden piezas móviles que pueden afectar al rendimiento y a la depuración.
  7. BuildKit cambió las características de rendimiento de docker build al mejorar el cacheo, el paralelismo y los pasos de build basados en mounts. Pero también hizo más visibles ciertos cuellos de botella del sistema de archivos.
  8. Las notificaciones de cambio de archivos en Windows difieren de Linux en casos límite; las pilas de recarga en caliente pueden comportarse distinto según si los eventos se puentean o se inspeccionan periódicamente.

De dónde viene realmente la velocidad: CPU, disco, montajes y red

CPU: usualmente no es el factor decisivo

Las cargas limitadas por CPU (compilaciones en Go/Rust, gzip, runners de tests que no golpean el disco) tienden a rendir de forma similar entre Desktop y WSL Engine porque ambos se ejecutan dentro del mismo entorno Linux respaldado por WSL2 en muchas configuraciones modernas. La frontera de la VM existe en ambos casos. La pregunta es: ¿añadiste por accidente capas extra (por ejemplo, usar Docker Desktop pero acceder a rutas de Windows con bind mounts pesados)?

E/S de disco: donde la mayoría pierde la semana

La palanca de velocidad más grande en desarrollo con contenedores en Windows es dónde están tus archivos de proyecto y cómo están montados.

  • Mejor caso: el código está almacenado dentro del sistema de archivos Linux de WSL2 (el ext4 de tu distro en un VHDX), y los contenedores usan volúmenes o bind mounts que permanecen dentro de Linux. Metadatos rápidos, operaciones de archivos pequeños rápidas.
  • Peor caso: el código está en NTFS (por ejemplo, C:\src) y lo montas en contenedores vía la frontera (/mnt/c/src o compartición de Desktop). Las cargas con muchos archivos pequeños sufren.

¿Por qué? Porque una operación “simple” como “stat 30,000 archivos” se convierte en una fiesta de traducción: mapeo de metadatos, mapeo de permisos, rarezas de sensibilidad a mayúsculas/minúsculas y invalidación de caché. node_modules de Node es básicamente una prueba de tortura de archivos pequeños. También lo son los entornos virtuales de Python y los registros de cargo de Rust.

Bind mounts vs volúmenes: tu contrato de rendimiento oculto

Los volúmenes viven en el backend de almacenamiento Linux de Docker (overlay2 sobre ext4 en WSL2). Normalmente son rápidos y predecibles. Los bind mounts reflejan una ruta del host dentro del contenedor. Si esa ruta está en Windows, pagas por cruzar la frontera. Si esa ruta está dentro de la distro WSL2, los bind mounts pueden estar bien.

Traducido a consejo: mantén tus dependencias dentro de Linux (volúmenes) incluso si tu código fuente debe permanecer en Windows. Mejor aún: mantén ambos en Linux y usa integración de editor para trabajar con rutas WSL.

Red: mayormente bien hasta que VPNs y localhost entran en juego

WSL2 usa redes virtuales con NAT. Docker añade su propia plomería de red virtual. Docker Desktop añade integración adicional para que localhost se comporte como la gente espera en Windows.

Los problemas de rendimiento en red suelen manifestarse como:

  • picos de latencia misteriosos cuando hay una VPN corporativa conectada
  • demoras en la resolución DNS dentro de contenedores
  • inconsistencias en el reenvío de puertos entre Windows ↔ WSL ↔ contenedor

Desktop tiende a “funcionar” más a menudo para publicación de puertos en Windows. WSL Engine puede ser más limpio para mallas de servicios Linux a Linux dentro de WSL, pero puede requerir más trabajo manual para que las herramientas de Windows vean los servicios.

Memoria y caché de páginas: la razón silenciosa por la que una configuración “se siente” más rápida

El caché de páginas de Linux es una superpotencia de rendimiento. Si tu carga vuelve a leer los mismos árboles de dependencias, el cacheo ayuda mucho. Pero el comportamiento de memoria de WSL2 (asignación dinámica y reclamación) puede hacer que el rendimiento se sienta inconsistente si la VM está escasa o se está reajustando constantemente. Desktop añade sus propios límites de recursos y controles en la interfaz, que pueden ser útiles—o pueden frenarte si están configurados demasiado bajos.

Quién es más rápido para qué: una matriz de decisión directa

No hay un “más rápido” universal. Hay más rápido según tu cuello de botella. Aquí lo práctico.

Si quieres máxima velocidad para desarrollo intensivo en sistema de archivos

Elige Docker Engine dentro de WSL2, y mantén tus repositorios dentro del sistema de archivos de WSL (\\wsl$ desde Windows; almacenamiento real bajo el VHDX de la distro). Usa herramientas nativas de Linux. Haz bind mount desde rutas Linux, no desde /mnt/c.

Si quieres la experiencia de desarrollador más predecible en una empresa mixta Windows

Elige Docker Desktop, especialmente si necesitas gestión GUI, ayudantes de credenciales, proxies corporativos, toggles de Kubernetes o menos tickets de “por qué localhost no funciona”. Pero aún así: guarda tu proyecto en WSL si te importa la velocidad.

Si tu cuello de botella son las compilaciones, no la recarga en caliente

Cualquiera de las dos configuraciones puede ser rápida. Lo que importa es BuildKit, la estrategia de cacheo y evitar invalidaciones innecesarias (copiar todo el repo temprano en el Dockerfile o reconstruir dependencias en cada edición).

Si estás en una VPN corporativa que rompe el DNS

Desktop suele tener mejores controles e integración. WSL Engine puede ser “más puro” pero te tocará depurar resolv.conf y el comportamiento del proxy DNS de Windows a última hora del día.

Broma #2: Nada acelera una reunión de “optimicemos Docker” como alguien diciendo “funciona en mi portátil”. Entonces todos los portátiles se convierten en evidencia.

Tareas prácticas: comandos, salida esperada y qué decisión tomar

Estas son comprobaciones reales que ejecutaría antes de creer el benchmark de alguien. Cada tarea incluye: comando, qué significa la salida y qué hacer después.

Task 1: Confirmar dónde está corriendo Docker (Desktop vs WSL Engine)

cr0x@server:~$ docker context ls
NAME                DESCRIPTION                               DOCKER ENDPOINT                             ERROR
default *           Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
desktop-linux       Docker Desktop                            unix:///var/run/docker.sock

Significado: Los contextos te dicen a qué demonio estás hablando. Si ves desktop-linux, probablemente estás usando la integración del demonio de Desktop.

Decisión: Si intentas comparar, cambia contextos explícitamente y vuelve a ejecutar las pruebas. No “supongas” que cambiaste; compruébalo.

Task 2: Identificar el demonio y el driver de almacenamiento

cr0x@server:~$ docker info --format '{{.ServerVersion}} {{.Driver}} {{.OperatingSystem}}'
27.3.1 overlay2 Docker Desktop

Significado: Overlay2 en Linux es típico. Si no ves overlay2, está pasando algo inusual. Si no es Linux, no estás en la ruta prevista.

Decisión: Si el driver de almacenamiento es inesperado, para. Tu investigación de rendimiento será ficción hasta que lo soluciones.

Task 3: Medir si tu proyecto está en el sistema de archivos Windows o WSL

cr0x@server:~$ pwd
/mnt/c/src/myapp

Significado: /mnt/c es NTFS de Windows montado en WSL. Si tu proyecto está aquí y lo estás montando, probablemente estás pagando el impuesto de la frontera.

Decisión: Si te importa la velocidad, mueve el repo al sistema Linux (por ejemplo, ~/src/myapp dentro de WSL) y vuelve a probar antes de cambiar cualquier otra cosa.

Task 4: Comparar operaciones intensivas en metadatos (la “prueba de node_modules” sin instalar nada)

cr0x@server:~$ time find . -type f | wc -l
48219

real    0m3.214s
user    0m0.112s
sys     0m0.988s

Significado: Esto aproxima el coste de recorrido de archivos pequeños. En /mnt/c, esto puede ser dramáticamente más lento que dentro de Linux.

Decisión: Si el tiempo sys es alto y real es mucho mayor de lo esperado, tu cuello de botella es la traducción del sistema de archivos. Arregla la ubicación/montajes, no la CPU.

Task 5: Comparar el rendimiento de bind mount dentro de un contenedor

cr0x@server:~$ docker run --rm -v "$PWD":/work -w /work alpine sh -lc 'time find . -type f >/dev/null'
real    0m4.02s
user    0m0.07s
sys     0m1.21s

Significado: Esto mide la ruta del bind mount desde la vista del contenedor. Si es mucho más lento que ejecutar find en el sistema anfitrión directamente, el puente del montaje es el culpable.

Decisión: Si es lento, cambia al repo en el lado Linux o usa volúmenes Docker para directorios con muchas dependencias.

Task 6: Confirmar si las escrituras del contenedor van a un volumen o a un bind mount

cr0x@server:~$ docker inspect -f '{{range .Mounts}}{{.Type}} {{.Source}} -> {{.Destination}}{{"\n"}}{{end}}' myapp
bind /mnt/c/src/myapp -> /app
volume myapp_node_modules -> /app/node_modules

Significado: Una configuración híbrida suele ser la mejor: código fuente vía bind mount, dependencias vía volumen.

Decisión: Si node_modules o target o .venv vive en un bind mount respaldado por Windows, muévelo a un volumen.

Task 7: Comprobar la versión de WSL y el estado de la distro (desde dentro de WSL)

cr0x@server:~$ wsl.exe -l -v
  NAME            STATE           VERSION
* Ubuntu-22.04    Running         2

Significado: Quieres WSL2 para rendimiento y compatibilidad con el kernel. WSL1 es otro mundo.

Decisión: Si estás en WSL1, migra. No tunees alrededor de eso.

Task 8: Comprobar si Docker Desktop es el demonio con el que estás hablando (la integración WSL puede confundir)

cr0x@server:~$ ps -ef | grep -E 'dockerd|containerd' | grep -v grep
root        2660       1  0 10:14 ?        00:00:02 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Significado: Si ves dockerd corriendo dentro de la distro WSL, probablemente estás ejecutando el Engine en WSL. Si no, puede que aún estés usando la integración de socket de Desktop.

Decisión: Decide quién posee el demonio: Desktop o systemd en WSL. Evita una propiedad mitad y mitad si quieres depuración predecible.

Task 9: Comprobar el estado de systemd en WSL (relevante para ejecutar Docker Engine correctamente)

cr0x@server:~$ ps -p 1 -o comm=
systemd

Significado: Si PID 1 es systemd, puedes gestionar Docker como un servicio Linux normal. Si no lo es, puede que estés usando métodos init alternativos.

Decisión: Si quieres estabilidad del Engine en WSL, habilita systemd y ejecuta Docker bajo él.

Task 10: Medir rendimiento de build (BuildKit activado, cache funcionando)

cr0x@server:~$ DOCKER_BUILDKIT=1 docker build -t myapp:bench .
[+] Building 18.2s (12/12) FINISHED
 => [internal] load build definition from Dockerfile                                      0.0s
 => => transferring dockerfile: 1.23kB                                                    0.0s
 => [internal] load metadata for docker.io/library/node:20-alpine                         0.8s
 => [1/6] FROM docker.io/library/node:20-alpine@sha256:...                                0.0s
 => [internal] load .dockerignore                                                         0.0s
 => => transferring context: 2.31kB                                                       0.0s
 => [2/6] WORKDIR /app                                                                    0.1s
 => [3/6] COPY package*.json ./                                                           0.1s
 => [4/6] RUN npm ci                                                                      14.9s
 => [5/6] COPY . .                                                                        1.5s
 => [6/6] RUN npm test                                                                    0.8s
 => exporting to image                                                                    0.0s

Significado: El paso lento es obvio. Si COPY . . es lento, la transferencia de contexto y la ruta del sistema de archivos están mal. Si npm ci es lento, estás limitado por I/O o por red.

Decisión: Si COPY es lento, arregla la ubicación del repo y .dockerignore. Si la instalación de dependencias es lenta, mueve directorios de caché a volúmenes y asegúrate de que tu DNS/proxy no esté estrangulando.

Task 11: Observar throttling de CPU del contenedor o contención del host

cr0x@server:~$ docker stats --no-stream
CONTAINER ID   NAME        CPU %     MEM USAGE / LIMIT     MEM %     NET I/O       BLOCK I/O      PIDS
c3a1d2e9f0b1   myapp       225.41%   612.3MiB / 7.6GiB     7.86%     12.4MB / 9MB  1.2GB / 38MB  34

Significado: Si la CPU está saturada y aún así vas lento, puede que estés limitado por cálculo, o te estén limitando CPUs asignadas.

Decisión: Si la CPU es alta y los pasos de build son intensivos en cómputo, asigna más CPUs/memoria a WSL2/Desktop o reduce el paralelismo en las herramientas.

Task 12: Comprobar uso de disco y dónde Docker guarda sus datos

cr0x@server:~$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          27        6         9.812GB   5.104GB (52%)
Containers      14        2         1.102GB   812.4MB (73%)
Local Volumes   19        7         22.44GB   8.201GB (36%)
Build Cache     45        0         3.993GB   3.993GB

Significado: El crecimiento de volúmenes y caché de build puede convertirse en “mi disco es lento” porque tu VHDX crece y el disco anfitrión se fragmenta o se ve presionado.

Decisión: Si lo recuperable es alto, limpia caché de build/volúmenes no usados. Si el disco anfitrión está casi lleno, deja de fingir que es un problema de Docker.

Task 13: Comprobar latencia DNS dentro de contenedores (lo “lento” en red a menudo es DNS)

cr0x@server:~$ docker run --rm alpine sh -lc 'time nslookup registry-1.docker.io >/dev/null'
real    0m0.42s
user    0m0.01s
sys     0m0.01s

Significado: Si DNS tarda segundos, las instalaciones de paquetes y los pulls se arrastrarán. Las VPNs y split-DNS corporativo pueden desencadenar esto.

Decisión: Si es lento, céntrate en la configuración DNS (comportamiento de resolv.conf en WSL, ajustes de proxy DNS de Desktop, reglas DNS corporativas), no en flags de Docker.

Task 14: Medir comportamiento de eventos en bind mounts para hot reloaders (inotify vs polling)

cr0x@server:~$ docker run --rm -v "$PWD":/work -w /work alpine sh -lc 'apk add --no-cache inotify-tools >/dev/null && inotifywait -t 2 -e modify . || echo timeout'
Setting up watches.
Watches established.
timeout

Significado: Si no recibes eventos de forma fiable, tu herramienta de recarga en caliente puede caer en polling, que consume CPU y “se siente” lento.

Decisión: Si los eventos no cruzan tu mount, mueve el código al sistema de archivos WSL o configura la herramienta para usar polling con intervalos razonables (y acepta el coste de CPU).

Guía rápida de diagnóstico (primeras/segundas/terceras comprobaciones)

Este es el orden que encuentra el cuello de botella más rápido en equipos reales. No teoría. Triage.

Primero: identifica la frontera que estás cruzando

  • ¿Tu repo está bajo /mnt/c?
  • ¿Estás haciendo bind mount de rutas de Windows en contenedores?
  • ¿Tus directorios de dependencias viven en montajes respaldados por Windows?

Si la respuesta es sí: espera operaciones de metadatos lentas. Arregla la ubicación de archivos/estrategia de montajes antes de tocar otra cosa.

Segundo: decide quién posee el demonio y mantenlo consistente

  • ¿Usas el demonio de Docker Desktop vía integración, o un dockerd que ejecutas dentro de WSL?
  • ¿Tienes ambos instalados y a veces cambias sin darte cuenta?

Si es inconsistente: tus medidas variarán. Elige uno, documéntalo y aplícalo con contextos o scripts del equipo.

Tercero: aisla build vs runtime vs red

  • ¿Build lento? Inspecciona la salida de docker build: ¿es COPY, instalaciones de dependencias o tests?
  • ¿Runtime lento? Revisa docker stats, patrones de escritura en disco y comportamiento de eventos del sistema de archivos.
  • ¿Pull/install lento? Comprueba la latencia DNS y el comportamiento de VPN/proxy.

Cuarto: comprueba límites de recursos y contención del host

  • ¿WSL/Desktop está limitado a 2 CPUs y 2GB de RAM porque alguien “optimizó” la configuración?
  • ¿El disco anfitrión está casi lleno o bajo escaneo agresivo de antivirus?

Si la respuesta es sí: no estás ajustando Docker; estás ajustando el entorno del host.

Tres mini-historias corporativas desde la trinchera

Incidente: la suposición equivocada de que “WSL = velocidad Linux”

Una empresa mediana desplegó portátiles Windows para un equipo de desarrollo que antes usaba estaciones Linux. El plan era simple: “Usad WSL2, ejecutad Docker, todo es básicamente Linux otra vez.” La primera semana, los ingenieros se quejaron de que las ejecuciones de tests y las instalaciones de dependencias eran dolorosamente lentas, pero solo en algunos repos.

El equipo asumió que el problema era la sobrecarga de Docker Desktop y empezó a desinstalar Desktop, cambiar a Docker Engine dentro de WSL y ajustar flags del demonio. Mejoró… ligeramente. No lo suficiente.

El verdadero culpable fue aburrido: los repos vivían en C:\ porque las políticas corporativas de backup y protección endpoint estaban vinculadas a rutas de Windows. Los desarrolladores editaban código con herramientas de Windows y WSL lo accedía vía /mnt/c. Sus bind mounts de contenedores cruzaban la frontera y la carga era una tormenta perfecta de operaciones de metadatos de archivos pequeños.

La solución no fue “cambiar Docker”. Fue una excepción de política y un cambio de flujo de trabajo: guardar los repos dentro de WSL para desarrollo activo, mantener artefactos “exportados” en Windows y usar la integración del IDE con WSL. La misma configuración de Docker de pronto pareció “más rápida” porque el sistema de archivos dejó de ser traductor de cada syscall.

Optimización que salió mal: dejar la VM sin recursos para “ahorrar batería”

Otro equipo quería que los portátiles funcionaran más fríos durante viajes. Alguien decidió recortar recursos de WSL2/Docker: menos CPUs, poca memoria, reclamación agresiva. En papel, redujo el ruido de los ventiladores. En la práctica, convirtió las builds en una ruleta.

Los síntomas fueron raros: la primera build tras reiniciar iba bien, la segunda era lenta, luego mejoraba, luego se atascaba otra vez. Los ingenieros culparon cachés, luego Docker, luego las ramas de los demás. Clásico.

El comportamiento oculto era presión de memoria. Con muy poca RAM, el caché de páginas de Linux no podía hacer su trabajo. Mientras tanto, compilaciones repetidas y escaneos de dependencias removían y reescribían el caché del sistema de archivos y desencadenaban un comportamiento parecido al swap dentro de la VM. Los límites de CPU amplificaron el dolor: menos paralelismo, mayor tiempo real, más tiempo para que procesos en segundo plano colisionaran.

Revirtieron a límites sensatos y luego hicieron explícita la política de ahorro de batería como opción opt-in. Moraleja: la “optimización” que quita margen tiende a crear jitter, y el jitter es lo que hace desconfiar a los ingenieros de cualquier otra métrica.

Práctica aburrida pero correcta que salvó el día: fijar el workflow y medir una cosa a la vez

Una organización grande tenía una mezcla de usuarios de Desktop y de WSL Engine. Llegaban quejas de rendimiento constantemente, pero cada ticket no servía: “Docker está lento.” Muy útil.

Un ingeniero con mentalidad SRE creó un breve “contrato Docker en Windows” interno: dónde viven los repos, cuál demonio es estándar, cómo montar dependencias y un script de benchmark mínimo que mide recorrido de archivos, tiempo de build y latencia DNS por separado. No era glamuroso. Era una lista de verificación.

Cuando ocurrió un incidente parecido a una caída —los desarrolladores no podían tirar imágenes y las pipelines se ralentizaron— el equipo ejecutó el script y vio inmediatamente picos de latencia DNS dentro de contenedores. Eso señaló un cambio de DNS corporativo interactuando con split tunneling de la VPN. Sin las pruebas base, habrían perdido días “ajustando Docker”.

Arreglaron la política de DNS, no Docker. La práctica aburrida fue la consistencia y la disciplina de medición, y se pagó sola la primera vez que algo raro ocurrió a escala.

Errores comunes: síntoma → causa raíz → solución

1) “npm install tarda una eternidad en contenedores”

Síntoma: las instalaciones de dependencias son 5–20× más lentas de lo esperado; la CPU está baja; la actividad de disco es constante.

Causa raíz: las dependencias se escriben en un bind mount respaldado por Windows (/mnt/c), provocando operaciones de metadatos lentas.

Solución: guarda el repo en el sistema de archivos WSL, o mantén node_modules en un volumen Docker y monta solo el código fuente.

2) “La recarga en caliente no se dispara, así que el servidor de desarrollo pollea y consume CPU”

Síntoma: los cambios de archivo a veces no se propagan; los ventiladores se aceleran; la recarga tarda.

Causa raíz: los eventos inotify no se puentean bien a través de ciertos montajes; la herramienta cae a polling.

Solución: mueve el repo al sistema de archivos WSL; configura el watcher para usar polling con intervalos razonables si debes permanecer en rutas de Windows.

3) “Docker build es lento en COPY”

Síntoma: COPY . . tarda segundos o minutos; la transferencia de contexto es pesada.

Causa raíz: contexto de build masivo por un .dockerignore deficiente; repo en ruta de Windows; muchos archivos pequeños.

Solución: mejora .dockerignore; reubica el repo; reordena el Dockerfile para maximizar cacheo (copiar primero manifests, luego instalar, luego copiar código).

4) “Pulls y apt installs se cuelgan aleatoriamente con la VPN”

Síntoma: pulls de imágenes se quedan estancados; installs de paquetes esperan resolución de nombres.

Causa raíz: DNS dentro de contenedores es lento o está roto por split-DNS de la VPN y NAT.

Solución: mide latencia DNS; ajusta configuración DNS para WSL/Desktop; coordina con IT para un resolutor correcto.

5) “A mí me va rápido pero a los nuevos hires les va lento”

Síntoma: algunas máquinas están bien, otras terribles, mismo repo.

Causa raíz: propiedad inconsistente del demonio (Desktop vs WSL Engine), ubicaciones de archivos inconsistentes, límites de recursos diferentes.

Solución: estandariza: una única configuración soportada, una recomendación de ubicación del repo, un script diagnóstico base.

6) “El espacio en disco desaparece y todo se vuelve más lento con el tiempo”

Síntoma: las builds se ralentizan; el disco está casi lleno; Docker reporta muchos datos recuperables.

Causa raíz: crecimiento de caché de builds y volúmenes; el VHDX de WSL se expande; presión en el disco anfitrión.

Solución: limpia imágenes/volúmenes/caché de build no usados; monitoriza el disco anfitrión; evita mantener capas antiguas indefinidamente.

Listas de verificación / plan paso a paso

Plan A: quieres el bucle de desarrollo más rápido en Windows

  1. Mueve los repos activos al sistema de archivos WSL: ~/src dentro de tu distro.
  2. Usa soporte del IDE para WSL para que la edición siga pareciendo nativa.
  3. Usa Docker Engine dentro de WSL2 si quieres capas mínimas, o Desktop si necesitas integración corporativa —pero guarda los archivos en WSL de todas formas.
  4. Monta el código vía ruta Linux. Mantén los directorios de dependencias en volúmenes.
  5. Mide: tiempo de recorrido de archivos, tiempo de recorrido en contenedor, tiempos de pasos de build, latencia DNS.

Plan B: debes mantener el código en C:\ por política corporativa

  1. Acepta que /mnt/c es más lento para archivos pequeños. No luches contra la física con mensajes en Slack.
  2. Usa volúmenes para directorios pesados de dependencias: node_modules, .venv, target, vendor, cachés de herramientas.
  3. Ajusta el comportamiento de los watchers: prefiere polling con intervalos sensatos antes que “esperar que inotify funcione”.
  4. Mejora .dockerignore para reducir la transferencia de contexto.
  5. Vigila excepciones de antivirus/endpoint (con aprobación de seguridad). Esos escáneres adoran masticar árboles de dependencias.

Plan C: estás optimizando builds, no desarrollo en vivo

  1. Activa BuildKit; confirma que el cache funciona.
  2. Reordena el Dockerfile para golpes de cache: copia primero lockfiles, instala deps, luego copia el código.
  3. Minimiza el contexto de build con .dockerignore.
  4. Separa problemas de red de problemas de disco con una comprobación de tiempos DNS.
  5. Usa builds multi-stage cuando reduzca el tamaño final sin aumentar tiempo de rebuild.

Preguntas frecuentes

1) ¿Docker Desktop siempre es más lento que Docker Engine en WSL2?

No. Para cargas limitadas por CPU suelen ser similares. Las mayores mejoras suelen venir de mantener los archivos dentro del sistema de archivos WSL y evitar bind mounts respaldados por NTFS.

2) ¿Cuál es la única mejora de rendimiento más importante?

Mueve tu repo desde C:\ (accedido como /mnt/c) al sistema de archivos de la distro WSL, luego haz bind mount desde allí. Elimina una capa de traducción de las rutas críticas.

3) ¿Por qué son lentos los bind mounts en Windows?

Los bind mounts que cruzan la frontera Windows ↔ Linux deben traducir semánticas del sistema de archivos. Las operaciones de metadatos en archivos pequeños se encarecen. Los volúmenes lo evitan quedándose en almacenamiento Linux.

4) ¿Puedo seguir usando editores de Windows si mi repo está en WSL?

Sí. La mayoría de editores modernos tienen integración con WSL. La clave es: guarda los archivos en Linux, edítalos vía un puente diseñado para ello y deja que los contenedores accedan sin cruzar NTFS.

5) ¿Debo desinstalar Docker Desktop si ejecuto Docker Engine en WSL?

Si no necesitas las características de Desktop, desinstalar puede reducir confusión y complejidad en segundo plano. Si tu organización depende de la integración de Desktop (proxies, almacenador de credenciales, soporte), mantenlo —pero sé explícito sobre qué demonio se usa.

6) ¿Por qué cambia mi rendimiento después de reiniciar o suspender?

El ciclo de vida de la VM de WSL2, la temperatura del caché de páginas y la asignación dinámica de memoria afectan la “sensación”. Cachés fríos hacen que todo parezca peor. Los límites de recursos pueden provocar inconsistencias.

7) ¿Kubernetes en Docker Desktop es un problema de rendimiento?

Puedes sufrir impacto principalmente porque consume CPU/RAM y añade churn en segundo plano. Si no lo usas, desactívalo. Si lo usas, asigna recursos de forma responsable.

8) ¿Los volúmenes Docker siempre son más rápidos que los bind mounts?

No siempre. Los volúmenes suelen ser más rápidos que bind mounts respaldados por Windows. Pero un bind mount dentro del sistema de archivos WSL puede ser perfectamente aceptable y más cómodo para flujos de desarrollo.

9) ¿Cómo sé si el cuello de botella es DNS?

Temporiza un nslookup dentro de un contenedor. Si tarda segundos, tus “pulls lentos” e “installs lentos” probablemente sean problemas de resolutor/VPN/proxy.

10) ¿Y si mi equipo usa Compose y va lento?

Compose amplifica problemas de sistema de archivos y watchers porque suele montar múltiples servicios desde el mismo repo. Arregla montajes y ubicación de archivos primero, luego mira el uso de recursos por servicio.

Siguientes pasos que realmente puedes hacer esta semana

  1. Elige una base: decide si tu estándar será Docker Desktop o WSL Engine. Estandariza contextos y scripts para que la gente no “compare” demonios distintos por accidente.
  2. Mueve un repo a WSL y vuelve a ejecutar dos mediciones: tiempo de recorrido find en el host y en un contenedor con bind mount. Si ves una caída grande, has encontrado tu palanca principal.
  3. Arregla montajes estratégicamente: mantén el código editable, pero mantén árboles de dependencias en volúmenes. Es el mejor compromiso cuando la política obliga rutas en Windows.
  4. Ejecuta la guía rápida de diagnóstico en la próxima queja de “Docker está lento”. Si no puedes decir si es sistema de archivos, DNS o límites de recursos, no estás diagnosticando —solo narrando.
  5. Documenta las reglas aburridas (ubicación de repos, montajes, comprobación DNS, higiene del caché de build). Así evitarás repetir la misma investigación de rendimiento en cada onboarding.

Si quieres una recomendación única y con opinión: pon tu código en el sistema de archivos Linux de WSL2 y deja de bind-montar NTFS en contenedores salvo que sea imprescindible. Docker Desktop vs WSL Engine es secundario; la frontera del sistema de archivos es la pelea final.

← Anterior
Visor de eventos para humanos: encuentra errores reales en 5 minutos
Siguiente →
Instalación de Ubuntu Server: mínima y realmente segura

Deja un comentario