Как я могу узнать, был ли я зарегистрирован в приватном реестре Docker из script?
Как я могу узнать, авторизован ли я на частном сервере реестра Docker из скрипта? Другими словами, успешно docker login some.registry.com
был выполнен docker login some.registry.com
(и все еще действителен)?
Примечание: я спрашиваю о произвольном частном реестре, а не о реестре docker.io
.
Ответы
Ответ 1
Если вход в docker работал, вы найдете папку .docker
в своем домашнем каталоге (~/.docker/
) с файлом config.json
с учетными данными в нем.
в противном случае вы получите ошибку входа в систему.
Примечание. Докеры определяют, какие учетные данные следует использовать, просмотрев имя реестра:
если вы делаете
docker pull myregistry.com/myimage:tag
docker будет выглядеть, если вы вошли в систему, а если не проверите, есть ли у вас учетные данные для реестра myregistry.com
и войдите в систему с ними.
Если вы не получите ошибку разрешения
Ответ 2
Это немного взломанный, но он работает в большинстве случаев для меня:
if ! grep -q "my.private.registry.com" ~/.docker/config.json ; then
docker login "my.private.registry.com"
fi
В принципе, вы выполняете поиск, если в ~/.docker/config.json
есть запись "my.private.registry.com". Однако, если сессия истекла, эта проверка не будет ее улавливать.
Ответ 3
Это немного глупо, я думаю, что до тех пор, пока у докера не появится команда для проверки входа в систему, хорошего решения не будет.
В вашем bash-скрипте вы можете попытаться войти в систему с тайм-аутом x секунд, если вы не вошли в систему, команда попытается запросить имя пользователя, а затем произойдет тайм-аут со статусом 124
. Если вы действительно вошли в систему, он просто снова войдет в систему с использованием учетных данных сохранения и продолжит работу со статусом 0
#!/bin/bash
timeout -s SIGKILL 3s docker login some.registry.com >/dev/null 2>&1
if [ $? -eq 0 ]
then
echo Logged In!
else
echo Not logged in...
fi
Ответ 4
Если вы ограничены в изучении вашей локальной системы, это невозможно узнать!
... Единственный способ убедиться, что хранитель учетных данных все еще действителен, - это выполнить операцию, которая приведет к их представлению в реестр, и проверить, принимает ли их реестр.
Если вы хотите использовать интерфейс командной строки Docker, чтобы получить ответ, то вы можете использовать @matanper с предложением "войти снова", которое завершится автоматически, если у вас все еще есть действительные учетные данные.
Другой способ - попытаться вытащить изображение, о котором известно, что оно не существует, которое будет отображать другое сообщение об ошибке при входе в систему или нет, например
# NO VALID LOGIN:
$ docker pull 999999999999.dkr.ecr.us-west-2.amazonaws.com/this/image:does_not_exist
Error response from daemon: pull access denied for 999999999999.dkr.ecr.us-west-2.amazonaws.com/this/image, repository does not exist or may require 'docker login'
против
# WITH VALID LOGIN:
$ docker pull 999999999999.dkr.ecr.us-west-2.amazonaws.com/this/image:does_not_exist
Error response from daemon: manifest for 999999999999.dkr.ecr.us-west-2.amazonaws.com/this/image:does_not_exist not found
(предположим, что вы не хотите pull
потому что вам не нужна задержка или передача больших данных, поэтому приведенный выше метод все еще в порядке)
В прошлом, когда Docker всегда сохранял учетные данные в ~/.docker/config.json
(или эквивалент для вашей ОС), вы могли анализировать этот файл, чтобы получить сохраненные в данный момент учетные данные, а затем запустить простую операцию со списком, используя curl
или подобный. Однако в последних версиях докера учетные данные хранятся в специальных хранилищах хост-ОС (например, в цепочке для ключей в Mac OS X), поэтому эта методика больше не является переносимой. Если переносимость не важна, вы все равно можете попробовать что-то подобное - хеш в config.json
- это просто имя пользователя и пароль, закодированные в base64, разделенные двоеточием, как это стандартно для базовой аутентификации HTTP, например в linux, с jq
для разбора JSON и base64
для декодирования base64:
$ cat ~/.docker/config.json | jq -r '.auths["registry.example.com"].auth' | base64 -d
username:password
Итак, завершив это с помощью операции списка реестра с помощью curl
:
REGISTRY="registry.example.com"
CREDENTIALS="$(cat ~/.docker/config.json | jq -r ".auths[\"${REGISTRY}\"].auth" | base64 -d)"
curl -sSf --max-time 3 --user "${CREDENTIALS}" "https://${REGISTRY}/v2/_catalog"
вернет код выхода ноль и ответ JSON, если КРЕДЕНТЫ хороши; или ненулевой код выхода, если нет
{
"repositories": [
"jamesjj/test-image",
"jamesjj/other-image",
...
...
}
ПРИМЕЧАНИЕ. При синтаксическом анализе JSON ключ адреса реестра может включать или не включать схему https://
зависимости от того, как был выполнен первоначальный вход в систему, поэтому cat ~/.docker/config.json | jq -r ".auths[\"${REGISTRY}\"].auth" | base64 -d)"
cat ~/.docker/config.json | jq -r ".auths[\"${REGISTRY}\"].auth" | base64 -d)"
cat ~/.docker/config.json | jq -r ".auths[\"${REGISTRY}\"].auth" | base64 -d)"
... может потребоваться: cat ~/.docker/config.json | jq -r ".auths[\"https://${REGISTRY}\"].auth" | base64 -d)"
Ответ 5
Когда вы выполните
Docker login <private registry> -u <user> -p <password>
с вашего терминала, вы получите ответ: (хранится в $?)
0
Login Succeeded
если вы были успешны.
В вашей оболочке script вы можете просто посмотреть ответ, который вы получаете, если он не равен 0, вам не удалось войти в систему.
sudo docker login <registry> -u <uname> -p <password>
if [ $? -ne 0 ]; then
echo Login failed!
else
echo Login OK!
fi
Ответ 6
Вы можете проанализировать .docker/config.json
и попробовать вручную подключиться к каждому реестру, указанному в файле. Файл содержит адрес реестра и закодированные имя пользователя и пароль, чтобы вы могли написать сценарий этого процесса. Вы можете сделать это, используя такую библиотеку, как docker-registry-client.
pip install docker-registry-client
А потом:
import base64
import docker_registry_client
import json
import os.path
def get_authed_registries():
result = []
config_path = os.path.expanduser("~/.docker/config.json")
if not os.path.isfile(config_path):
print("No docker config")
return []
docker_config = json.load(open(config_path))
for registry, auth in docker_config.get("auths", {}).items():
username, password = base64.b64decode(auth["auth"]).decode("utf-8").split(":", 1)
if not registry:
registry = "https://index.docker.io/v1/"
if not registry.startswith("http"):
registry = "https://" + registry
try:
rc = docker_registry_client.DockerRegistryClient(registry, username=username, password=password)
result.append(registry)
except Exception, e:
print(registry, "failed:", e)
return result
get_authed_registries()
Несколько предостережений:
- Это может не сработать, если вы используете хранилище учетных данных.
- Проверено на Python 2.7. Может потребоваться небольшие корректировки для Python 3.
- Этот код работает для проверки подлинности, но дальнейшие действия в реестре не выполняются. Для этого вам потребуется удалить версию API (
/v1
, /v2
и т.д.) Из имени хоста. - Код предполагает, что все реестры являются HTTPS (если не указано иное в
config.json
) - Еще более правильная версия, вероятно, удалит все, кроме имени хоста, и попробует v1 и v2.
Тем не менее, я смог получить список зарегистрированных реестров, и он правильно проигнорировал истекший логин ECR.
Ответ 7
Я считаю, что сообщение об ошибке будет зависеть от реализации реестра. Тем не менее, моя собственная техника - извлечь изображение, которое не существует, и проанализировать любое сообщение об ошибке:
$!/bin/sh
repo="$1"
msg=$(docker pull ${repo}/missing:missing 2>&1)
case "$msg" in
*"requested access to the resource is denied"*|*"pull access denied"*)
echo "Logged out";;
*"manifest unknown"*|*"not found"*)
echo "Logged in, or read access for anonymous allowed";;
*"Pulling from"*)
echo "Missing image was not so missing after all?";;
*)
echo "Unknown message: $msg";;
esac
Это было проверено с помощью автономного реестра docker и docker_auth. Вы захотите проверить с реестрами, с которыми вы можете столкнуться.
Если ваш сервер реестра разрешает анонимные извлечения и вы хотите проверить, возможна ли отправка, вы можете создать пустое пустое изображение и заменить извлечение нажатием этого изображения. Например
#!/bin/sh
repo=$1
# note, I do not like the "." here, better to change it to an empty directory
# see "mktemp" for an option if you cannot make your own empty directory somewhere
docker build -t "${repo}/empty:test" -f - . <<EODF
FROM scratch
EODF
msg=$(docker push "${repo}/empty:test" 2>&1)
rc=$?
if [ "$rc" = "0" ]; then
echo "Access granted to push"
else
case "$msg" in
*"requested access to the resource is denied"*)
echo "Access denied";;
*)
echo "Unknown error message: $msg";;
esac
fi