Сообщение об ошибке
Error response from daemon: Get "https://registry.example.com:5000/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority
Хост и порт реестра у вас будут свои; docker push, pull и login сообщают об ошибке одинаково: «Error response from daemon: Get \"https://<registry>/v2/\": …». containerd, nerdctl, Podman и узлы Kubernetes, скачивающие образы, выводят тот же текст x509 со своими префиксами.
Docker Engine (dockerd) — docker pull / push / login against a registry with an untrusted certificate
Что это означает
Демон Docker (а не CLI docker) попытался обратиться к API реестра по пути /v2/ и не смог проверить его TLS-сертификат: цепочка не ведёт к CA, которому доверяет демон. dockerd доверяет системному пакету сертификатов CA (CA bundle) хоста, а также CA для отдельных реестров, размещённым в /etc/docker/certs.d/<registry>:<port>/. Обычные причины — частные реестры с корпоративными сертификатами и прокси с инспекцией TLS.
Почему это происходит
Собственный реестр с частным сертификатом
частоHarbor, реестр GitLab, Nexus или registry:2 с сертификатом от корпоративного или самостоятельно созданного CA.
Прокси с инспекцией TLS перед Docker Hub или другими реестрами
частоДемон видит сертификаты прокси; если корневого сертификата прокси нет в хранилище хоста, любое скачивание образа завершается ошибкой.
CA установлен туда, где демон его не ищет
иногдаКопирование CA в хранилище клиентской машины ничего не даёт, если демон работает в другом месте (виртуальная машина Docker Desktop, удалённый DOCKER_HOST, CI-раннер). Имя каталога в certs.d должно точно совпадать с хостом и портом реестра.
Реестр не отдаёт свой промежуточный сертификат
иногдаGo (dockerd) не загружает промежуточные сертификаты сам; реестр, который отдаёт только конечный сертификат, не проходит проверку даже с публичным CA.
Как исправить
- 1.
Установите CA для этого реестра в certs.d
/etc/docker/certs.d/<host>:<port>/ca.crt читается при каждом запросе; в воспроизведении docker login прошёл успешно сразу после добавления этого файла.
bash # Trust the registry's CA for this registry only (no daemon restart needed) sudo mkdir -p /etc/docker/certs.d/registry.example.com:5000 sudo cp corp-root-ca.pem /etc/docker/certs.d/registry.example.com:5000/ca.crt docker login registry.example.com:5000 - 2.
Установите CA на уровне системы и перезапустите dockerd
Для прокси и при большом количестве реестров добавьте корневой сертификат в пакет сертификатов хоста; демон читает его при запуске.
bash # Or system-wide (proxy roots, many registries), then restart the daemon sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt sudo update-ca-certificates sudo systemctl restart docker - 3.
Docker Desktop: настройте доверие корневому сертификату на хосте
Виртуальная машина Docker Desktop при запуске берёт доверенные корневые сертификаты из операционной системы хоста, поэтому установите корневой сертификат там и перезапустите Docker Desktop.
text Docker Desktop: the daemon runs in a VM. Add the root to the host's trust store (macOS Keychain "System" with "Always Trust", Windows "Trusted Root Certification Authorities") and restart Docker Desktop; it imports trusted host roots into the VM. - 4.
Проверьте цепочку сертификатов реестра
Если отправляется только конечный сертификат, настройте реестр или его обратный прокси на отдачу полной цепочки.
bash openssl s_client -connect registry.example.com:5000 -servername registry.example.com -showcerts </dev/null 2>/dev/null \ | grep -E '^ *[0-9]+ s:|^ *i:'
Связанные ошибки
x509: certificate signed by unknown authorityGo crypto/x509tls: failed to verify certificate: x509: certificate signed by unknown authorityGo crypto/tls (Go ≥ 1.20)http: server gave HTTP response to HTTPS clientGo net/httpUnable to connect to the server: tls: failed to verify certificate: x509: certi…kubectl (client-go)