Prueba de velocidad de mirrors Docker: 3 métodos + script de cambio automático

¿Te ha pasado alguna vez? El pipeline de CI/CD se queda atascado en el 99 % de un docker pull, el log repite “connection timeout” y “TLS handshake timeout”, y el despliegue lleva diez minutos parado.
La semana pasada me pasó en un proyecto. No era una caída a las tres de la madrugada, pero tras siete reintentos, cambiar el mirror a mano y reiniciar el daemon de Docker, casi media hora hasta resolverlo. Lo peor: no sabes qué mirror funciona. El acelerador de Alibaba Cloud limita mucho fuera de sus propios servidores, el mirror de la USTC dejó de ofrecer servicio en junio del año pasado, y esos mirrors “de alta velocidad” de terceros a veces ni siquiera pasan una prueba básica de conectividad.
De ahí la pregunta: ¿cómo medir la velocidad rápido y encontrar el mirror más rápido en tu red actual?
En este artículo no te daré una lista de direcciones para probar una a una (hay demasiados de esos). Hablaré de la lógica técnica de la medición, las ventajas e inconvenientes de tres métodos, y dos scripts listos para usar (Shell y Python). Al final comparto datos reales de mirrors en China medidos en mayo de 2026, para que sepas cuáles funcionan de verdad hoy.
Comparación de métodos: ping, HTTP HEAD y pull real
Hay tres enfoques habituales: ping, HTTP HEAD y pull real de imagen. Cada uno tiene pros y contras; la tabla resume las diferencias.
| Método | Principio | Ventajas | Desventajas | Caso de uso |
|---|---|---|---|---|
| Ping | Tiempo de respuesta ICMP | Simple y rápido | No refleja la velocidad de descarga; muchos servidores bloquean ping | Filtrado inicial |
| HTTP HEAD | Endpoint /v2/ de la Registry API | API estándar; verifica soporte V2 | Solo conectividad, no velocidad de descarga | Validar disponibilidad |
| Pull real | docker pull de una imagen real | Refleja la velocidad real con precisión | Lento; consume ancho de banda | Verificación final |
¿Por qué ping no basta?
Mucha gente prueba ping primero: un comando y ves la latencia. Pero ping mide ICMP, algo distinto de descargar una imagen.
Ejemplo: un mirror puede tener ICMP desactivado (común en la nube por seguridad), ping da timeout y HTTP funciona bien. Al revés: un nodo CDN con 20 ms de ping puede ir lento por rutas, TLS o límites de ancho de banda.
HTTP HEAD: la práctica estándar
La Registry API v2 define un endpoint de salud: /v2/. Un HEAD o GET que devuelva 200 OK indica soporte V2 y disponibilidad.
La lógica central:
curl -I -m 5 https://docker.xuanyuan.me/v2/
Si ves HTTP/2 200, el mirror responde. El tiempo hasta recibir la cabecera aproxima la latencia de red: no es velocidad de descarga, pero sirve para conectividad y respuesta.
Pull real: la verificación más fiable
Lo más fiable es docker pull de una imagen real. Uso Alpine (~5 MB): pequeña, rápida, poco ancho de banda.
time docker pull alpine:latest
Mira el tiempo real: de la petición al fin del pull. Con tamaño de imagen / tiempo obtienes la velocidad media, la que notarás en despliegues.
Inconveniente: lento. Un mirror tarda segundos o decenas de segundos; diez mirrors, varios minutos. Además, el caché difiere entre mirrors y puede sesgar la comparación.
Mi recomendación: HTTP HEAD para filtrar mirrors con buena conectividad (descartar los lentos o caídos), luego pull real para validar los 3–5 más rápidos. Eficiente y fiable.
Implementación en Shell: medición y cambio automático con un clic
Si eres de operaciones o sueles tocar servidores, un script Shell es lo más directo. Este script mide en paralelo, ordena resultados y actualiza daemon.json.
Lógica central: medición concurrente + ordenación
Define una lista de mirrors, prueba /v2/ con curl, ordena y escribe los más rápidos en /etc/docker/daemon.json.
Función de medición:
#!/bin/bash
# Lista de mirrors (verificados en mayo de 2026)
MIRRORS=(
"https://docker.xuanyuan.me"
"https://docker.1ms.run"
"https://docker.m.daocloud.io"
"https://atomhub.openatom.cn"
)
# Probar tiempo de respuesta de un mirror (milisegundos)
test_mirror() {
local mirror=$1
local start=$(date +%s%N)
local http_code=$(curl -s -o /dev/null -w "%{http_code}" \
--connect-timeout 5 \
--max-time 10 \
"$mirror/v2/")
local end=$(date +%s%N)
local elapsed=$(( (end - start) / 1000000 ))
if [[ "$http_code" == "200" ]]; then
echo "$elapsed|$mirror"
else
echo "999999|$mirror" # Marcar fallos con valor muy alto
fi
}
Detalle: date +%s%N da nanosegundos; al dividir entre 1000000 obtienes milisegundos. Mirrors con código distinto de 200 se marcan como 999999 ms y quedan al final al ordenar.
Medición concurrente: xargs multihilo
Probar diez mirrors uno a uno es lento. Uso xargs -P:
# Medir todos los mirrors en paralelo
results=$(printf "%s\n" "${MIRRORS[@]}" | \
xargs -P 4 -I {} bash -c 'test_mirror "$@"' _ {})
# Ordenar por tiempo de respuesta (ascendente)
sorted=$(echo "$results" | sort -t '|' -k1 -n)
# Mostrar resultados ordenados
echo "Resultados (menor tiempo = mejor):"
echo "$sorted" | while IFS='|' read time url; do
if [[ "$time" != "999999" ]]; then
echo " ${time}ms $url"
else
echo " [fallo] $url"
fi
done
xargs -P 4 lanza 4 hilos. Ajusta según el servidor: 2–4 en pruebas, 8–10 en producción si hace falta.
Actualizar daemon.json automáticamente
Último paso: escribir los 3 mirrors más rápidos.
# Extraer los 3 mirrors más rápidos
top3=$(echo "$sorted" | grep -v "999999" | head -n 3 | cut -d '|' -f 2)
# Construir array JSON
mirrors_json=$(echo "$top3" | sed 's/.*/"&"/' | tr '\n' ',' | sed 's/,$//')
# ⚠️ Advertencia: sobrescribir pierde la configuración existente
# Si daemon.json ya tiene otros campos (data-root, log-driver), combínalos a mano
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": [$mirrors_json]
}
EOF
echo "daemon.json actualizado, mirrors más rápidos:"
echo "$top3"
# Reiniciar Docker (requiere root)
if [[ $EUID -eq 0 ]]; then
systemctl restart docker
echo "Servicio Docker reiniciado; configuración aplicada"
else
echo "Se necesita root para reiniciar Docker. Ejecuta: sudo systemctl restart docker"
fi
Uso
Guarda el script como docker-mirror-test.sh y dale permiso de ejecución:
chmod +x docker-mirror-test.sh
sudo ./docker-mirror-test.sh # root para modificar daemon.json
Salida típica:
Resultados (menor tiempo = mejor):
45ms https://docker.xuanyuan.me
68ms https://docker.1ms.run
120ms https://docker.m.daocloud.io
[fallo] https://atomhub.openatom.cn
daemon.json actualizado, mirrors más rápidos:
https://docker.xuanyuan.me
https://docker.1ms.run
https://docker.m.daocloud.io
Ojo: si ya tienes otras opciones en Docker (data-root, log-driver), sobrescribir daemon.json las borra. Es más seguro leer la config existente y añadir registry-mirrors. La versión Python hace eso; te la recomiendo si tienes config previa.
Implementación en Python: cronometraje preciso y manejo de errores
Si Shell no es lo tuyo, o quieres tiempos más precisos y mejor manejo de errores, Python con requests controla timeouts y excepciones, y funciona en macOS, Windows y Linux.
Función central de medición
import requests
import time
import json
from pathlib import Path
# Lista de mirrors (verificados en mayo de 2026)
MIRRORS = [
"https://docker.xuanyuan.me",
"https://docker.1ms.run",
"https://docker.m.daocloud.io",
"https://atomhub.openatom.cn",
]
def test_mirror(url, timeout=5):
"""Probar tiempo de respuesta de un mirror (milisegundos)"""
start = time.time()
try:
r = requests.head(
f"{url}/v2/",
timeout=timeout,
allow_redirects=True,
headers={"User-Agent": "docker-mirror-test/1.0"}
)
elapsed = (time.time() - start) * 1000 # convertir a ms
if r.status_code == 200:
return elapsed, url
else:
return float('inf'), url
except requests.exceptions.RequestException:
return float('inf'), url
Uso allow_redirects=True porque algunos mirrors redirigen a CDN; hay que medir la respuesta final. El User-Agent evita bloqueos por bots en ciertos CDN.
Medición concurrente: ThreadPoolExecutor
concurrent.futures ofrece un pool más flexible que xargs:
from concurrent.futures import ThreadPoolExecutor, as_completed
def test_all_mirrors(mirrors, max_workers=4):
"""Probar todos los mirrors en paralelo"""
results = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
future_to_url = {
executor.submit(test_mirror, url): url
for url in mirrors
}
for future in as_completed(future_to_url):
elapsed, url = future.result()
results.append((elapsed, url))
return sorted(results, key=lambda x: x[0])
as_completed devuelve resultados al terminar cada tarea, sin bloquear. Puedes subir max_workers a 8 o más según CPU y red.
Actualizar daemon.json (conservando la config existente)
Esta versión lee daemon.json actual y actualiza registry-mirrors sin borrar el resto:
def update_daemon_json(fastest_mirrors, daemon_path="/etc/docker/daemon.json"):
"""Actualizar daemon.json conservando la configuración existente"""
path = Path(daemon_path)
# Leer configuración existente
if path.exists():
config = json.loads(path.read_text())
else:
config = {}
# Actualizar registry-mirrors
config["registry-mirrors"] = fastest_mirrors[:3]
# Escribir configuración
path.write_text(json.dumps(config, indent=2))
print(f"Actualizado {daemon_path}, mirrors más rápidos:")
for m in fastest_mirrors[:3]:
print(f" {m}")
def main():
print("Midiendo velocidad de mirrors...")
results = test_all_mirrors(MIRRORS)
print("\nResultados (menor tiempo = mejor):")
for elapsed, url in results:
if elapsed != float('inf'):
print(f" {elapsed:.0f}ms {url}")
else:
print(f" [fallo] {url}")
# Extraer mirrors válidos
valid_mirrors = [url for elapsed, url in results if elapsed != float('inf')]
if valid_mirrors:
update_daemon_json(valid_mirrors)
print("\nReinicia Docker para aplicar: sudo systemctl restart docker")
else:
print("\nTodos los mirrors fallaron; revisa red o la lista de mirrors")
if __name__ == "__main__":
main()
Uso
Guarda como docker-mirror-test.py y ejecuta:
python3 docker-mirror-test.py
Ejemplo de salida:
Midiendo velocidad de mirrors...
Resultados (menor tiempo = mejor):
42ms https://docker.xuanyuan.me
71ms https://docker.1ms.run
118ms https://docker.m.daocloud.io
[fallo] https://atomhub.openatom.cn
Actualizado /etc/docker/daemon.json, mirrors más rápidos:
https://docker.xuanyuan.me
https://docker.1ms.run
https://docker.m.daocloud.io
Reinicia Docker para aplicar: sudo systemctl restart docker
La versión Python es un poco más lenta (~10–20 ms de overhead), pero más precisa y robusta. Si tu daemon.json ya tiene varios campos, Python es más seguro y no pisa el resto.
Datos reales de mirrors en China (mayo 2026)
El estado de los mirrors cambia rápido: lo que funcionaba el año pasado puede estar caído; lo rápido el mes pasado puede estar limitado hoy. Resumo mediciones de mayo de 2026.
Mirrors disponibles (mediciones)
| Mirror | Dirección | Velocidad media | Estabilidad | Notas |
|---|---|---|---|---|
| Xuanyuan | https://docker.xuanyuan.me | 12.3 MB/s | 99.2% | Multiplataforma; operación conforme en China |
| 1ms | https://docker.1ms.run | 11.8 MB/s | 99.5% | SLA de nivel financiero; preferido en empresas |
| DaoCloud | https://docker.m.daocloud.io | 9.5 MB/s | 97.6% | Servicio consolidado; opción de respaldo |
| AtomHub | https://atomhub.openatom.cn | 8.2 MB/s | 100% | Proyecto oficial de la OpenAtom Foundation |
Datos de un informe de la comunidad Tencent Cloud (2026-03), verificados con HTTP HEAD; encajan en general. Xuanyuan y 1ms son los más rápidos y estables; conviene probarlos primero.
Mirrors ya no válidos (2024–2026)
Estos funcionaron antes pero hoy están caídos o muy limitados:
| Mirror | Dirección | Estado | Notas |
|---|---|---|---|
| USTC | https://docker.mirrors.ustc.edu.cn | ❌ Detenido | Dejó servicio externo en junio de 2024 |
| NetEase | http://hub-mirror.c.163.com | ❌ Detenido | Sin sincronización; imágenes obsoletas |
| Acelerador oficial Alibaba Cloud | https://registry.cn-hangzhou.aliyuncs.com | ⚠️ Muy limitado | Fuerte throttling fuera de ECS Alibaba; no recomendado |
El acelerador de Alibaba es una trampa habitual: en un servidor Tencent Cloud, pulls con timeout frecuentes; Alibaba limita tráfico ajeno a su nube. En ECS Alibaba va bien; entre nubes distintas, no cuentes con ello.
NAS y desarrolladores en China
En Synology o Zspace, cambiar la config de Docker no es tan simple como en un servidor; algunos sistemas bloquean editar daemon.json.
En ese caso recomiendo AtomHub (OpenAtom Foundation): proyecto de beneficio público, sin throttling ni cobro, estabilidad 100 %. Más lento que Xuanyuan o 1ms, pero usable. No depende de un cloud concreto; experiencia coherente entre plataformas.
Nota de vigencia: el estado de los mirrors cambia rápido; estos datos son de mayo de 2026. Usa los scripts anteriores de forma periódica o un cron semanal para actualizar la config.
Buenas prácticas para daemon.json
Tras medir, toca configurar el daemon. Una buena config permite conmutación: si falla el primer mirror, Docker prueba el siguiente.
Configuración recomendada
{
"registry-mirrors": [
"https://docker.xuanyuan.me",
"https://docker.1ms.run",
"https://docker.m.daocloud.io"
]
}
Con 2–3 mirrors basta. Docker prueba en orden y usa el primero que responda; el resto no se usa. Demasiados mirrors añaden coste de resolución y pueden incluir fuentes muertas.
Mecanismo de conmutación de Docker
Así funciona registry-mirrors:
- Ejecutas
docker pull ubuntu:latest - Docker intenta primero
docker.xuanyuan.me - Si timeout o error, pasa a
docker.1ms.run - Si todos fallan, vuelve a Docker Hub oficial
Ventaja: un mirror caído no para el despliegue. Inconveniente: si el primero responde lento pero no falla, Docker no salta al más rápido.
Por eso tiene sentido medir de vez en cuando: el más rápido primero, el segundo en segunda posición.
Verificar que la config aplica
Tras cambiar, reinicia Docker:
sudo systemctl restart docker
Comprueba los mirrors:
docker info | grep -A 5 "Registry Mirrors"
Salida esperada:
Registry Mirrors:
https://docker.xuanyuan.me/
https://docker.1ms.run/
https://docker.m.daocloud.io/
Si lo ves, la config está activa y los pulls usarán esos mirrors con prioridad.
Rutas en macOS y Windows
Con Docker Desktop la ruta es distinta:
- macOS: Docker Desktop → Settings → Docker Engine → editar JSON
- Windows: Settings → Docker Engine, igual
El contenido JSON es el mismo; solo cambia la UI. Tras editar, “Apply & Restart”.
daemon.json admite más campos: data-root, log-driver, storage-driver, etc. Combínalos con registry-mirrors en un solo JSON; no sobrescribas todo. Python ya lo hace; en Shell debes fusionar a mano.
Resumen
En esencia, tres ideas:
-
Métodos de medición: HTTP HEAD para filtrar mirrors con buena conectividad; pull real para validar los más rápidos. No uses ping: mide ICMP, no velocidad de descarga.
-
Scripts automáticos: Shell para despliegue rápido en ops; Python para precisión y multiplataforma. Ambos pueden actualizar
daemon.jsonsin configurar a mano. -
Elección de mirror: en mayo de 2026, Xuanyuan y 1ms son los más rápidos y estables; AtomHub encaja en NAS y escenarios de beneficio público. Deja de usar USTC, NetEase y el acelerador Alibaba limitado fuera de su nube.
Qué hacer ahora:
- Descarga el script (Shell o Python) y mide mirrors en tu red
- Programa un cron o systemd timer semanal para rem medir y actualizar: los mirrors cambian rápido
- Si gestionas CI/CD del equipo, integra la medición antes del despliegue para evitar alertas nocturnas por pull fallido
Si te ha servido, compártelo con el equipo o la comunidad. El tema de mirrors es habitual y mucha gente sigue cambiando a mano; les ahorrarás tiempo.
FAQ
¿Le ping suffit-il pour choisir un miroir Docker ?
¿Qué méthode donne le benchmark le plus fiable ?
¿Cómo automatiser le choix du meilleur miroir ?
11 min de lectura · Publicado el: 27 may 2026 · Actualizado el: 21 ago 2026
Guía práctica de Docker
Si llegaste desde búsqueda, lo más rápido es ir al artículo anterior o siguiente de esta misma serie.
Anterior
Guía de mirrors de Docker en China 2026: resuelve pull timeout en 5 minutos
Disponibilidad actual de Docker mirror en China en 2026: configura daemon.json, prueba mirrors, gestiona proxy corporativo y pull-through cache, y distingue un límite de Docker Hub (429) de un mirror caído para resolver Docker pull timeout.
Parte 23 de 38
Siguiente
Timeouts al hacer pull de Docker en redes corporativas: guía completa de DNS, proxy y mirrors
¿Docker pull con timeout en la red corporativa? Esta guía ofrece un flujo completo de diagnóstico: DNS, proxy y mirrors. Incluye la lista de mirrors verificados en mayo de 2026 para localizar y resolver el problema rápido.
Parte 25 de 38



Comentarios
Inicia sesión con GitHub para dejar un comentario