Alternar tema

Teste de velocidade de mirrors Docker: 3 métodos + scripts de troca automática

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

Você já passou por isso? O pipeline de CI/CD fica preso em 99% no docker pull, os logs repetem “connection timeout” e “TLS handshake timeout”, e o deploy já está parado há dez minutos.

Na semana passada, um dos meus projetos caiu exatamente nessa armadilha. Não chegou a derrubar uma implantação de madrugada, mas foram 7 tentativas seguidas, cada uma exigindo trocar manualmente o mirror, reiniciar o Docker daemon e tentar de novo. Quase meia hora perdida. O pior é que você nem sabe qual mirror ainda funciona: o acelerador da Alibaba Cloud limita bastante servidores fora da própria nuvem, o mirror da USTC parou em junho do ano passado, e alguns mirrors de terceiros que prometem ser “rápidos” às vezes nem passam em um teste básico de conectividade.

Isso leva a uma pergunta bem prática: como testar rapidamente e encontrar o mirror Docker mais rápido para o seu ambiente de rede atual?

Este texto não vai só listar uma pilha de endereços para você testar um por um, porque esse tipo de artigo já existe aos montes. O foco aqui é outro: a lógica técnica por trás do teste de velocidade, os prós e contras de três métodos de medição e dois scripts de automação prontos para usar, em Shell e Python. No final, também compartilho dados testados em maio de 2026 sobre mirrors disponíveis na China, para você saber quais fontes ainda são realmente utilizáveis.


Comparando métodos de teste: ping, HTTP HEAD e pull real

Existem três formas comuns de testar mirrors Docker: teste com ping, teste com HTTP HEAD e pull real de uma imagem. Cada uma tem vantagens e limitações. A tabela abaixo resume as diferenças.

MétodoPrincípioVantagensLimitaçõesMelhor uso
Teste com pingTempo de resposta ICMPSimples e rápidoNão reflete a velocidade real de download; alguns servidores bloqueiam pingTriagem inicial
Teste com HTTP HEADEndpoint /v2/ da Registry APIAPI padronizada; valida suporte a V2Mede conectividade, não velocidade de downloadVerificação de disponibilidade
Pull realdocker pull de uma imagem realÉ o reflexo mais fiel da velocidade realDemora mais e consome bandaValidação final

Por que ping não é preciso o suficiente?

Muita gente pensa primeiro em ping, porque é simples: uma linha de comando já mostra a latência. Só que ping mede resposta ICMP, e isso não tem nada a ver diretamente com o download real de uma imagem Docker.

Um exemplo: determinado servidor de mirror pode bloquear ICMP, como muitos provedores de nuvem fazem por segurança. Nesse caso, o ping mostra timeout, mas as requisições HTTP funcionam normalmente. O contrário também acontece: alguns nós de CDN respondem ping em 20ms, mas a requisição HTTP passa por redirecionamentos, negociação TLS e limitação de banda. Na prática, o download fica lento demais.

O jeito padrão de testar com HTTP HEAD

A especificação Docker Registry API v2 define um endpoint de verificação de saúde: /v2/. Você envia uma requisição HEAD ou GET para esse endpoint. Se receber 200 OK, significa que aquela Registry suporta a API V2 e está disponível naquele momento.

A lógica central é esta:

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

Se você vir HTTP/2 200, esse mirror está acessível. O tempo de resposta, medido desde o envio da requisição até o recebimento dos headers, dá uma boa noção de latência de rede. Não é velocidade de download, mas já permite avaliar conectividade e rapidez de resposta.

Pull real: a validação mais fiel

O método mais confiável é, claro, fazer docker pull de uma imagem real. Eu costumo usar Alpine, que tem cerca de 5 MB, porque é pequena, baixa rápido e não consome tanta banda.

time docker pull alpine:latest

Observe o tempo real: ele representa o tempo total desde o início da requisição até a conclusão do pull. A partir daí, você pode calcular a velocidade média de download, dividindo o tamanho da imagem pelo tempo total. Essa é a velocidade que você vai sentir de verdade durante um deploy.

Mas esse método tem um problema: é lento. Testar um mirror pode levar de alguns segundos a dezenas de segundos. Testar dez mirrors pode tomar alguns minutos. Além disso, pode haver diferença de cache entre os mirrors: alguns já têm Alpine em cache, outros não. Isso afeta a comparação.


Minha recomendação: primeiro use HTTP HEAD para filtrar rapidamente os mirrors conectáveis, removendo os que não respondem ou respondem muito devagar. Depois use pull real para validar os 3 a 5 candidatos mais rápidos. Assim você ganha eficiência sem abrir mão de um resultado confiável.


Script Shell: teste de velocidade e troca automática em um comando

Se você trabalha com operações ou vive ajustando servidores, um script Shell provavelmente é o caminho mais rápido. Escrevi um script que testa mirrors em paralelo, ordena os resultados automaticamente e atualiza o daemon.json. Dá para usar direto.

Lógica principal: teste paralelo + ordenação automática

A ideia do script é simples: definir uma lista de mirrors, testar o endpoint /v2/ de cada um com curl, ordenar os resultados por tempo de resposta, selecionar os mais rápidos e modificar /etc/docker/daemon.json.

Veja primeiro a função de teste:

#!/bin/bash

# Lista de mirrors testados como disponíveis em maio de 2026
MIRRORS=(
    "https://docker.xuanyuan.me"
    "https://docker.1ms.run"
    "https://docker.m.daocloud.io"
    "https://atomhub.openatom.cn"
)

# Testa o tempo de resposta de um mirror em milissegundos
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"  # Mirrors com falha recebem um valor muito alto
    fi
}

Há um detalhe importante aqui: uso date +%s%N para pegar um timestamp em nanossegundos e divido por 1000000 para converter o tempo para milissegundos. Mirrors que falham, ou seja, que não retornam status HTTP 200, recebem 999999 milissegundos. Assim eles caem para o fim da ordenação.

Teste paralelo com xargs

Testar dez mirrors um por um é lento demais. Por isso uso xargs -P para paralelizar:

# Testa todos os mirrors em paralelo
results=$(printf "%s\n" "${MIRRORS[@]}" | \
    xargs -P 4 -I {} bash -c 'test_mirror "$@"' _ {})

# Ordena por tempo de resposta em ordem crescente
sorted=$(echo "$results" | sort -t '|' -k1 -n)

# Exibe o resultado ordenado
echo "Resultado do teste de velocidade (quanto menor o tempo de resposta, melhor):"
echo "$sorted" | while IFS='|' read time url; do
    if [[ "$time" != "999999" ]]; then
        echo "  ${time}ms  $url"
    else
        echo "  [falha]  $url"
    fi
done

xargs -P 4 significa executar 4 tarefas em paralelo. Você pode ajustar esse número conforme o servidor: em ambiente de teste, 2 a 4 já costuma bastar; em produção, 8 a 10 pode fazer sentido.

Atualizando o daemon.json automaticamente

O último passo é gravar os 3 mirrors mais rápidos no daemon.json.

# Extrai os 3 mirrors mais rápidos
top3=$(echo "$sorted" | grep -v "999999" | head -n 3 | cut -d '|' -f 2)

# Monta o array JSON
mirrors_json=$(echo "$top3" | sed 's/.*/"&"/' | tr '\n' ',' | sed 's/,$//')

# Atenção: sobrescrever diretamente pode apagar configurações existentes.
# Se o seu daemon.json já tiver outros campos, como data-root ou log-driver,
# faça o merge manualmente.
cat > /etc/docker/daemon.json <<EOF
{
  "registry-mirrors": [$mirrors_json]
}
EOF

echo "daemon.json atualizado. Mirrors mais rápidos:"
echo "$top3"

# Reinicia o serviço Docker; requer permissão de root
if [[ $EUID -eq 0 ]]; then
    systemctl restart docker
    echo "Serviço Docker reiniciado. A configuração já está ativa."
else
    echo "Permissão de root necessária para reiniciar o Docker. Execute manualmente: sudo systemctl restart docker"
fi

Como usar

Salve o script como docker-mirror-test.sh e adicione permissão de execução com chmod +x:

chmod +x docker-mirror-test.sh
sudo ./docker-mirror-test.sh  # Requer root para modificar daemon.json

Depois da execução, você verá uma saída parecida com esta:

Resultado do teste de velocidade (quanto menor o tempo de resposta, melhor):
  45ms   https://docker.xuanyuan.me
  68ms   https://docker.1ms.run
  120ms  https://docker.m.daocloud.io
  [falha] https://atomhub.openatom.cn

daemon.json atualizado. Mirrors mais rápidos:
https://docker.xuanyuan.me
https://docker.1ms.run
https://docker.m.daocloud.io

Vale reforçar uma pegadinha: se o servidor já tiver outras configurações Docker, como data-root ou log-driver, sobrescrever o daemon.json diretamente vai apagar esses campos. O caminho mais seguro é ler a configuração atual e apenas adicionar ou substituir registry-mirrors, em vez de sobrescrever tudo. O script em Python abaixo faz exatamente isso, então recomendo priorizá-lo quando a configuração for mais complexa.


Script Python: temporização mais precisa e melhor tratamento de erro

Se você não se sente tão à vontade com Shell, ou precisa de temporização mais precisa e tratamento de erro melhor, a versão em Python fica mais tranquila. A biblioteca requests permite controlar timeout com precisão, capturar exceções variadas e ainda roda em macOS, Windows e Linux.

Função principal de teste

import requests
import time
import json
from pathlib import Path

# Lista de mirrors testados como disponíveis em maio 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):
    """Testa o tempo de resposta de um mirror em milissegundos."""
    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  # Converte para milissegundos
        if r.status_code == 200:
            return elapsed, url
        else:
            return float('inf'), url
    except requests.exceptions.RequestException:
        return float('inf'), url

Aqui também há um detalhe: uso allow_redirects=True porque alguns mirrors redirecionam para nós de CDN, e o que importa é o tempo de resposta final. Também adiciono um User-Agent para reduzir o risco de algum CDN tratar a requisição como scraping e bloqueá-la.

Teste paralelo com ThreadPoolExecutor

O módulo concurrent.futures do Python oferece um pool de threads, mais flexível que xargs:

from concurrent.futures import ThreadPoolExecutor, as_completed

def test_all_mirrors(mirrors, max_workers=4):
    """Testa todos os mirrors em 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 devolve os resultados conforme cada tarefa termina, evitando bloqueios desnecessários. Você pode usar max_workers=8 ou mais, dependendo do desempenho do servidor e da largura de banda.

Atualizando daemon.json sem apagar a configuração existente

Esta versão lê o daemon.json atual e adiciona o campo registry-mirrors, em vez de sobrescrever o arquivo inteiro:

def update_daemon_json(fastest_mirrors, daemon_path="/etc/docker/daemon.json"):
    """Atualiza o daemon.json preservando a configuração existente."""
    path = Path(daemon_path)

    # Lê a configuração atual
    if path.exists():
        config = json.loads(path.read_text())
    else:
        config = {}

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

    # Grava a configuração
    path.write_text(json.dumps(config, indent=2))
    print(f"{daemon_path} atualizado. Mirrors mais rápidos:")
    for m in fastest_mirrors[:3]:
        print(f"  {m}")

def main():
    print("Testando mirrors Docker...")
    results = test_all_mirrors(MIRRORS)

    print("\nResultado do teste de velocidade (quanto menor o tempo de resposta, melhor):")
    for elapsed, url in results:
        if elapsed != float('inf'):
            print(f"  {elapsed:.0f}ms  {url}")
        else:
            print(f"  [falha]  {url}")

    # Extrai mirrors válidos
    valid_mirrors = [url for elapsed, url in results if elapsed != float('inf')]

    if valid_mirrors:
        update_daemon_json(valid_mirrors)
        print("\nReinicie o serviço Docker para aplicar a configuração: sudo systemctl restart docker")
    else:
        print("\nTodos os mirrors falharam. Verifique a rede ou a lista de mirrors.")

if __name__ == "__main__":
    main()

Como usar

Salve o script como docker-mirror-test.py e execute:

python3 docker-mirror-test.py

Exemplo de saída:

Testando mirrors Docker...

Resultado do teste de velocidade (quanto menor o tempo de resposta, melhor):
  42ms   https://docker.xuanyuan.me
  71ms   https://docker.1ms.run
  118ms  https://docker.m.daocloud.io
  [falha] https://atomhub.openatom.cn

/etc/docker/daemon.json atualizado. Mirrors mais rápidos:
  https://docker.xuanyuan.me
  https://docker.1ms.run
  https://docker.m.daocloud.io

Reinicie o serviço Docker para aplicar a configuração: sudo systemctl restart docker

Na prática, a versão em Python é um pouco mais lenta que a versão Shell, algo como 10 a 20 ms de overhead. Em troca, ela oferece mais precisão e lida melhor com erros. Se a configuração Docker do seu servidor for mais complexa, a versão Python é mais segura, porque não apaga outros campos.


Dados testados de mirrors na China em 2026

O estado dos mirrors muda rápido: o que funcionava no ano passado pode ter parado este ano; o que era rápido no mês passado pode estar limitado agora. Organizei abaixo os dados testados em maio de 2026 como referência.

Mirrors disponíveis testados

MirrorEndereçoVelocidade médiaEstabilidadeObservações
Xuanyuan Mirrorhttps://docker.xuanyuan.me12,3 MB/s99,2%Suporte multiplataforma, operação compatível dentro da China
1ms Mirrorhttps://docker.1ms.run11,8 MB/s99,5%SLA de nível financeiro, boa opção para empresas
DaoCloudhttps://docker.m.daocloud.io9,5 MB/s97,6%Serviço antigo, útil como opção de backup
AtomHubhttps://atomhub.openatom.cn8,2 MB/s100%Projeto público oficial da OpenAtom Foundation

Esses dados vêm de um relatório testado da comunidade de desenvolvedores da Tencent Cloud, de março de 2026. Eu também validei com HTTP HEAD e os números parecem basicamente consistentes. Xuanyuan Mirror e 1ms Mirror foram os mais rápidos e estáveis, então são os primeiros que eu testaria.

Mirrors que já perderam utilidade entre 2024 e 2026

Estes mirrors já foram utilizáveis, mas hoje estão descontinuados ou com limitação pesada:

MirrorEndereçoStatusObservações
USTChttps://docker.mirrors.ustc.edu.cnDescontinuadoParou de atender publicamente em junho de 2024
NetEasehttp://hub-mirror.c.163.comDescontinuadoSincronização encerrada; imagens desatualizadas
Acelerador oficial da Alibaba Cloudhttps://registry.cn-hangzhou.aliyuncs.comLimitação pesadaLimita servidores fora da Alibaba Cloud; não recomendo

Sendo bem direto, eu também já caí na pegadinha do acelerador da Alibaba Cloud. Configurei esse acelerador em um servidor da Tencent Cloud e o pull de imagens vivia dando timeout. Só depois entendi que a Alibaba Cloud limita bastante servidores que não estão na própria infraestrutura. Se você usa Alibaba Cloud ECS, o acelerador pode ser realmente rápido. Em ambientes de outros provedores, não conte com isso.

A situação de usuários de NAS e desenvolvedores na China

Se você usa NAS da Synology ou da ZSpace, escolher mirror pode ser ainda mais chato. Alterar a configuração Docker em um NAS não é tão simples quanto em um servidor comum, e alguns sistemas até bloqueiam a edição do daemon.json.

Nesse caso, minha sugestão é usar AtomHub, projeto oficial da OpenAtom Foundation. Ele tem caráter público, não limita tráfego e não cobra. A estabilidade foi de 100%. A velocidade não bate Xuanyuan ou 1ms, mas pelo menos é estável e disponível. Além disso, o AtomHub não depende de um provedor de nuvem específico, então a experiência tende a ser mais consistente entre plataformas.


Nota sobre validade temporal: o estado dos mirrors muda rápido, e os dados deste texto vão até maio de 2026. Antes de usar em produção, rode os scripts de teste acima periodicamente, ou configure uma tarefa agendada para testar e atualizar a configuração toda semana.


Boas práticas para configurar daemon.json

Depois do teste de velocidade, o próximo passo é configurar o Docker daemon. Uma configuração correta permite tolerância a falhas: se o primeiro mirror falhar, o Docker tenta o próximo automaticamente.

Configuração recomendada

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

Configurar 2 ou 3 mirrors já é suficiente. Não coloque mirrors demais: o Docker tenta em ordem e retorna assim que o primeiro disponível responde. Os seguintes nem chegam a ser usados. Uma lista longa só aumenta o custo de resolução e a chance de incluir fontes inválidas.

Como funciona a tolerância a falhas do Docker

O campo registry-mirrors do Docker daemon funciona assim:

  1. Você executa docker pull ubuntu:latest
  2. O Docker tenta primeiro o primeiro mirror: docker.xuanyuan.me
  3. Se o primeiro mirror der timeout ou retornar erro, o Docker troca automaticamente para o segundo: docker.1ms.run
  4. Se todos os mirrors falharem, só então ele volta para a fonte oficial do Docker Hub

A vantagem é clara: se um mirror cair, seu deploy não precisa parar. A desvantagem também existe: se o primeiro mirror estiver lento, mas não falhar, o Docker continua usando ele e não muda automaticamente para uma opção mais rápida.

Por isso, testar periodicamente faz sentido. O mirror mais rápido deve ficar em primeiro, e o segundo mais rápido deve ficar logo depois.

Verificando se a configuração entrou em vigor

Depois de alterar a configuração, reinicie o serviço Docker:

sudo systemctl restart docker

Em seguida, valide se os mirrors foram aplicados:

docker info | grep -A 5 "Registry Mirrors"

Você verá algo parecido com isto:

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

Se isso aparecer, a configuração funcionou. A partir daí, ao baixar imagens, o Docker vai priorizar esses mirrors.

Caminho de configuração no macOS e no Windows

Se você usa Docker Desktop no macOS ou no Windows, o caminho de configuração é diferente:

  • macOS: abra Docker Desktop → Settings → Docker Engine → edite o JSON
  • Windows: o mesmo caminho, em Settings → Docker Engine

O conteúdo da configuração é igual; o que muda é a interface. Depois de editar, clique em “Apply & Restart”, e o Docker Desktop reinicia automaticamente.


Vale lembrar: o daemon.json também pode conter outros campos, como data-root, para caminho de armazenamento das imagens, log-driver, para driver de logs, e storage-driver, para driver de armazenamento. Se você já usa esses campos, combine-os com registry-mirrors no mesmo JSON. Não sobrescreva o arquivo inteiro. A versão Python do script já cuida disso; na versão Shell, você precisa fazer o merge manualmente.


Resumo

Depois de tudo isso, a ideia central cabe em três pontos:

  1. Método de teste: primeiro use HTTP HEAD para filtrar mirrors conectáveis; depois use pull real para validar os candidatos mais rápidos. Não use ping como critério principal, porque ele mede resposta ICMP e não tem relação direta com velocidade de download.

  2. Scripts de automação: a versão Shell serve para deploy rápido em operações; a versão Python é melhor para medição mais precisa e uso multiplataforma. As duas conseguem atualizar daemon.json automaticamente e reduzem o trabalho manual.

  3. Escolha de mirrors: em testes de maio de 2026, Xuanyuan Mirror e 1ms Mirror foram os mais rápidos e estáveis; AtomHub é uma boa opção para usuários de NAS e cenários públicos. Mirrors já inválidos, como USTC, NetEase e a versão limitada da Alibaba Cloud, devem ficar fora da configuração.


Recomendações práticas:

  • Baixe o script de teste deste texto, em Shell ou Python, e meça os mirrors no seu ambiente de rede atual
  • Configure uma tarefa agendada, com cron ou systemd timer, para testar e atualizar a configuração toda semana. Mirrors mudam rápido; só a validação recorrente dá segurança
  • Se você cuida do CI/CD de uma equipe, integre o script ao pipeline e valide a disponibilidade dos mirrors antes do deploy. Isso evita alertas no meio da noite por falha no pull de imagens

Por fim, se este texto foi útil, vale compartilhar com o time ou com outros desenvolvedores do seu grupo. Problemas com mirrors Docker são bem comuns, e muita gente ainda perde tempo trocando fonte manualmente.

15 min de leitura · Publicado em: 27 mai 2026 · Atualizado em: 14 jul 2026

Comentários

Entre com GitHub para comentar

Easton BlogEaston Blog