Changer le thème

Test de vitesse des miroirs Docker : 3 méthodes + script de bascule automatique

Easton editorial illustration: large image-pull speedometer with one winning range

Vous avez déjà vécu ça : le pipeline CI/CD bloqué à 99 % sur un docker pull, les logs qui répètent « connection timeout » et « TLS handshake timeout », alors que votre déploiement est déjà en retard de dix minutes ?

La semaine dernière, un de mes projets est tombé dans ce piège. Pas de déploiement nocturne raté, mais sept tentatives d’affilée, à chaque fois un changement manuel de miroir et un redémarrage du daemon Docker — près d’une demi-heure perdue. Le plus agaçant : impossible de savoir quel miroir fonctionne vraiment. L’accélérateur Alibaba Cloud limite fortement hors de leurs serveurs, le miroir de l’USTC s’est arrêté en juin de l’année dernière, et les sources tierces « ultra-rapides » ne passent parfois même pas un test de connectivité fiable.

D’où la question : comment mesurer rapidement la vitesse et trouver le miroir le plus rapide dans votre environnement réseau actuel ?

Je ne vais pas vous balancer une liste d’adresses de miroirs à tester une par une (il y en a déjà trop). L’article couvre le principe technique du benchmark, les avantages et inconvénients de trois méthodes, et deux scripts prêts à l’emploi (Shell et Python). En fin de parcours, des données de miroirs domestiques mesurées en mai 2026 pour savoir lesquels sont réellement utilisables aujourd’hui.


Comparaison des méthodes — ping, HTTP HEAD et pull réel

Trois approches dominent pour tester les miroirs : ping, requête HTTP HEAD et pull d’image réel. Chacune a ses forces et faiblesses ; le tableau suivant résume les différences.

MéthodePrincipeAvantagesInconvénientsCas d’usage
Test pingTemps de réponse ICMPSimple, rapideNe reflète pas le débit réel ; ping souvent bloquéPré-filtrage
Test HTTP HEADEndpoint Registry API /v2/API standard, valide le support V2Connectivité seulement, pas le débitValidation de disponibilité
Test par pull réeldocker pull d’une vraie imageReflète le mieux la vitesse réelleLong, consomme de la bande passanteValidation finale

Pourquoi le ping n’est pas assez précis ?

Beaucoup commencent par un ping : une ligne de commande, la latence s’affiche. Mais le ping mesure ICMP, pas du tout le téléchargement d’images.

Exemple : un serveur miroir peut bloquer ICMP (fréquent chez les clouds pour la sécurité) — ping en timeout alors que HTTP fonctionne. À l’inverse, un nœud CDN à 20 ms en ping peut ralentir fortement en HTTP à cause du routage, de TLS ou des limites de bande passante.

La bonne pratique HTTP HEAD

La spécification Docker Registry API v2 définit un point de contrôle : /v2/. Un HEAD ou GET qui renvoie 200 OK indique un Registry V2 disponible.

Logique de base :

curl -I -m 5 https://docker.xuanyuan.me/v2/

Si vous voyez HTTP/2 200, le miroir répond. Le temps jusqu’aux en-têtes reflète grossièrement la latence — pas le débit, mais connectivité et réactivité.

Pull réel : la validation la plus fiable

Le plus fiable reste docker pull d’une image réelle. J’utilise souvent Alpine (~5 Mo) : petit, rapide, peu de bande passante.

time docker pull alpine:latest

Regardez le temps real — de la requête à la fin du pull. Taille de l’image / durée totale ≈ débit moyen, proche de ce que vous vivrez en déploiement.

Inconvénient : lent. Quelques secondes à dizaines de secondes par miroir ; dix miroirs = plusieurs minutes. Le cache peut aussi fausser la comparaison (Alpine déjà en cache sur un miroir, pas sur un autre).


Mon conseil : HTTP HEAD pour filtrer rapidement les miroirs joignables, puis pull réel sur les 3 à 5 premiers. Efficace et fiable.


Implémentation Shell — benchmark et bascule en une commande

Pour l’ops ou ceux qui bricolent souvent les serveurs, un script Shell est le plus direct. Voici un script concurrent, tri automatique et mise à jour de daemon.json, prêt à copier.

Cœur : benchmark concurrent + tri

Idée : liste de miroirs, curl sur /v2/ pour mesurer le temps de réponse, tri, sélection des plus rapides, écriture dans /etc/docker/daemon.json.

Fonction de test :

#!/bin/bash

# 镜像源列表(2026年5月实测可用)
MIRRORS=(
    "https://docker.xuanyuan.me"
    "https://docker.1ms.run"
    "https://docker.m.daocloud.io"
    "https://atomhub.openatom.cn"
)

# 测试单个镜像源响应时间(毫秒)
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"  # 失败的源标记为极大值
    fi
}

Détail : date +%s%N pour des timestamps en nanosecondes, division par 1 000 000 pour des millisecondes. Échec (code HTTP ≠ 200) → 999999 ms, trié en dernier.

Concurrence : xargs multi-thread

Dix miroirs en série, c’est long. xargs -P pour la parallélisation :

# 并发测速所有镜像源
results=$(printf "%s\n" "${MIRRORS[@]}" | \
    xargs -P 4 -I {} bash -c 'test_mirror "$@"' _ {})

# 按响应时间排序(升序)
sorted=$(echo "$results" | sort -t '|' -k1 -n)

# 输出排序结果
echo "测速结果(响应时间越短越好):"
echo "$sorted" | while IFS='|' read time url; do
    if [[ "$time" != "999999" ]]; then
        echo "  ${time}ms  $url"
    else
        echo "  [失败]  $url"
    fi
done

xargs -P 4 = 4 threads. Ajustez selon la machine — 2–4 en test, 8–10 possible en prod.

Mise à jour automatique de daemon.json

Dernière étape : écrire les 3 miroirs les plus rapides.

# 提取最快的 3 个镜像源
top3=$(echo "$sorted" | grep -v "999999" | head -n 3 | cut -d '|' -f 2)

# 构造 JSON 数组
mirrors_json=$(echo "$top3" | sed 's/.*/"&"/' | tr '\n' ',' | sed 's/,$//')

# ⚠️ 警告:直接覆盖会丢失现有配置!
# 如果你的 daemon.json 已有其他字段(data-root、log-driver),请手动合并
cat > /etc/docker/daemon.json <<EOF
{
  "registry-mirrors": [$mirrors_json]
}
EOF

echo "已更新 daemon.json,最快镜像源:"
echo "$top3"

# 重启 Docker 服务(需要 root 权限)
if [[ $EUID -eq 0 ]]; then
    systemctl restart docker
    echo "Docker 服务已重启,配置生效"
else
    echo "需要 root 权限重启 Docker,请手动执行:sudo systemctl restart docker"
fi

Utilisation

Enregistrez le script sous docker-mirror-test.sh, rendez-le exécutable :

chmod +x docker-mirror-test.sh
sudo ./docker-mirror-test.sh  # 需要 root 权限修改 daemon.json

Sortie typique :

测速结果(响应时间越短越好):
  45ms   https://docker.xuanyuan.me
  68ms   https://docker.1ms.run
  120ms  https://docker.m.daocloud.io
  [失败] https://atomhub.openatom.cn

已更新 daemon.json,最快镜像源:
https://docker.xuanyuan.me
https://docker.1ms.run
https://docker.m.daocloud.io

Attention : si daemon.json contient déjà d’autres réglages (data-root, log-driver), l’écrasement direct les efface. Plus sûr : lire la config existante et fusionner registry-mirrors. La version Python le fait ; privilégiez-la dans ce cas.


Implémentation Python — chronométrage précis et gestion d’erreurs

Si Shell vous semble opaque, ou si vous voulez un timing plus fin et une meilleure gestion d’erreurs, Python convient mieux. requests contrôle les timeouts et les exceptions ; le script tourne sur macOS, Windows et Linux.

Fonction de benchmark

import requests
import time
import json
from pathlib import Path

# 镜像源列表(2026年5月实测可用)
MIRRORS = [
    "https://docker.xuanyuan.me",
    "https://docker.1ms.run",
    "https://docker.m.daocloud.io",
    "https://atomhub.openatom.cn",
]

def test_mirror(url, timeout=5):
    """测试单个镜像源响应时间(毫秒)"""
    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  # 转换为毫秒
        if r.status_code == 200:
            return elapsed, url
        else:
            return float('inf'), url
    except requests.exceptions.RequestException:
        return float('inf'), url

allow_redirects=True suit les redirections CDN. Un User-Agent évite certains blocages anti-bot.

Concurrence : ThreadPoolExecutor

from concurrent.futures import ThreadPoolExecutor, as_completed

def test_all_mirrors(mirrors, max_workers=4):
    """并发测试所有镜像源"""
    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 renvoie les tâches au fur et à mesure. max_workers=8 ou plus selon CPU et réseau.

Mise à jour de daemon.json (config existante conservée)

Lecture du fichier actuel, ajout de registry-mirrors sans écraser le reste :

def update_daemon_json(fastest_mirrors, daemon_path="/etc/docker/daemon.json"):
    """更新 daemon.json,保留原有配置"""
    path = Path(daemon_path)

    # 读取现有配置
    if path.exists():
        config = json.loads(path.read_text())
    else:
        config = {}

    # 更新 registry-mirrors
    config["registry-mirrors"] = fastest_mirrors[:3]

    # 写入配置
    path.write_text(json.dumps(config, indent=2))
    print(f"已更新 {daemon_path},最快镜像源:")
    for m in fastest_mirrors[:3]:
        print(f"  {m}")

def main():
    print("正在测速镜像源...")
    results = test_all_mirrors(MIRRORS)

    print("\n测速结果(响应时间越短越好):")
    for elapsed, url in results:
        if elapsed != float('inf'):
            print(f"  {elapsed:.0f}ms  {url}")
        else:
            print(f"  [失败]  {url}")

    # 提取有效镜像源
    valid_mirrors = [url for elapsed, url in results if elapsed != float('inf')]

    if valid_mirrors:
        update_daemon_json(valid_mirrors)
        print("\n请重启 Docker 服务使配置生效:sudo systemctl restart docker")
    else:
        print("\n所有镜像源均失败,请检查网络或镜像源列表")

if __name__ == "__main__":
    main()

Utilisation

Enregistrez sous docker-mirror-test.py :

python3 docker-mirror-test.py

Exemple de sortie :

正在测速镜像源...

测速结果(响应时间越短越好):
  42ms   https://docker.xuanyuan.me
  71ms   https://docker.1ms.run
  118ms  https://docker.m.daocloud.io
  [失败] https://atomhub.openatom.cn

已更新 /etc/docker/daemon.json,最快镜像源:
  https://docker.xuanyuan.me
  https://docker.1ms.run
  https://docker.m.daocloud.io

请重启 Docker 服务使配置生效:sudo systemctl restart docker

En pratique, Python ajoute ~10–20 ms d’overhead mais gagne en précision et robustesse. Config Docker complexe : préférez Python pour ne pas écraser d’autres champs.


Données mesurées des miroirs domestiques en 2026

L’état des miroirs change vite — ce qui marchait l’an dernier peut être arrêté ; ce qui était rapide le mois dernier peut être limité. Données de mai 2026 à titre de référence.

Miroirs disponibles (mesures)

MiroirAdresseDébit moyenStabilitéRemarques
Xuanyuanhttps://docker.xuanyuan.me12,3 Mo/s99,2 %Multi-plateforme, exploitation conforme en Chine
1mshttps://docker.1ms.run11,8 Mo/s99,5 %SLA niveau finance, choix entreprise
DaoCloudhttps://docker.m.daocloud.io9,5 Mo/s97,6 %Service établi, option de secours
AtomHubhttps://atomhub.openatom.cn8,2 Mo/s100 %Projet officiel OpenAtom, à but non lucratif

Source : rapport de la communauté développeurs Tencent Cloud (2026-03), recoupé par nos tests HTTP HEAD. Xuanyuan et 1ms sont les plus rapides et stables — à mettre en tête de liste.

Miroirs obsolètes (2024–2026)

MiroirAdresseÉtatRemarques
USTChttps://docker.mirrors.ustc.edu.cn❌ ArrêtéService public arrêté en juin 2024
NetEasehttp://hub-mirror.c.163.com❌ ArrêtéSync stoppée, images obsolètes
Accélérateur Alibaba officielhttps://registry.cn-hangzhou.aliyuncs.com⚠️ Limitation forteLimitation hors ECS Alibaba ; déconseillé

L’accélérateur Alibaba : sur un serveur Tencent Cloud, pulls souvent en timeout — limitation cross-cloud. Sur ECS Alibaba, c’est une autre histoire ; entre clouds, ne comptez pas dessus.

NAS et développeurs en Chine

Sur Synology ou Zspace, modifier Docker est plus pénible ; certains NAS verrouillent daemon.json.

Dans ce cas, AtomHub (OpenAtom) : gratuit, sans limitation agressive, stabilité 100 %. Moins rapide que Xuanyuan ou 1ms, mais fiable et indépendant d’un cloud donné.


Rappel de fraîcheur : l’état des miroirs évolue vite ; données arrêtées à mai 2026. Lancez régulièrement les scripts ci-dessus ou un cron hebdomadaire pour rafraîchir la config.


Bonnes pratiques pour daemon.json

Après le benchmark, configurez le daemon Docker pour basculer automatiquement si le premier miroir échoue.

Configuration recommandée

{
  "registry-mirrors": [
    "https://docker.xuanyuan.me",
    "https://docker.1ms.run",
    "https://docker.m.daocloud.io"
  ]
}

Deux ou trois miroirs suffisent. Docker essaie dans l’ordre et s’arrête au premier qui répond ; au-delà, peu d’intérêt et risque de sources mortes.

Mécanisme de repli Docker

Pour docker pull ubuntu:latest :

  1. Docker tente le premier miroir : docker.xuanyuan.me
  2. Timeout ou erreur → bascule vers le second : docker.1ms.run
  3. Tous en échec → repli sur Docker Hub

Avantage : un miroir en panne n’arrête pas le déploiement. Inconvénient : un miroir lent mais « vivant » reste utilisé — d’où l’intérêt de re-benchmarker et de remettre le plus rapide en premier.

Vérifier que la config est active

Après modification, redémarrez Docker :

sudo systemctl restart docker

Puis :

docker info | grep -A 5 "Registry Mirrors"

Sortie attendue :

Registry Mirrors:
 https://docker.xuanyuan.me/
 https://docker.1ms.run/
 https://docker.m.daocloud.io/

Les pulls utiliseront alors ces miroirs en priorité.

Chemins macOS et Windows

Avec Docker Desktop :

  • macOS : Docker Desktop → Settings → Docker Engine → éditer le JSON
  • Windows : idem dans Settings → Docker Engine

Même contenu JSON, interface différente. « Apply & Restart » redémarre Docker Desktop.


daemon.json peut aussi définir data-root, log-driver, storage-driver, etc. Fusionnez tout dans un seul JSON — ne remplacez pas aveuglément. La version Python fusionne ; en Shell, fusionnez à la main.


Synthèse

Trois idées à retenir :

  1. Méthodes : HTTP HEAD pour filtrer, pull réel pour valider le top. Pas de ping pour juger le débit — ICMP ≠ téléchargement.

  2. Scripts : Shell pour déploiement ops rapide ; Python pour précision et multi-plateforme. Les deux peuvent mettre à jour daemon.json.

  3. Choix 2026 : en mai 2026, Xuanyuan et 1ms sont les plus rapides et stables ; AtomHub pour NAS et usage associatif. Abandonnez USTC, NetEase et l’accélérateur Alibaba limité hors cloud Alibaba.


Actions concrètes :

  • Téléchargez et exécutez le script (Shell ou Python) sur votre réseau
  • Planifiez un cron ou un timer systemd hebdomadaire — l’état des miroirs change vite
  • En équipe CI/CD, intégrez le test avant déploiement pour éviter les alertes nocturnes sur un pull bloqué

Si l’article vous a aidé, partagez-le : beaucoup de collègues changent encore de miroir à la main — quelques minutes gagnées pour eux aussi.

FAQ

Le ping suffit-il pour choisir un miroir Docker ?
Non. Le ping mesure l'ICMP et peut être bloqué ou ne pas refléter le débit du registre. Utilisez-le seulement comme préfiltre, puis vérifiez l'endpoint /v2/ et terminez par un vrai docker pull.
Quelle méthode donne le benchmark le plus fiable ?
Un pull réel d'une petite image mesure le mieux l'expérience complète, notamment DNS, TLS, métadonnées et téléchargement. Supprimez l'effet du cache et répétez le test pour comparer les miroirs équitablement.
Comment automatiser le choix du meilleur miroir ?
Filtrez d'abord les endpoints joignables avec une requête HTTP, mesurez plusieurs fois leur latence, puis effectuez un pull sur les meilleurs candidats. Ne modifiez daemon.json qu'après validation et conservez une configuration de secours.

11 min de lecture · Publié le: 27 mai 2026 · Mis à jour le: 27 juil. 2026

Commentaires

Connectez-vous avec GitHub pour laisser un commentaire

Easton BlogEaston Blog