docker login 은 자격증명을 ~/.docker/config.json 에 저장한다. 이 파일이 깨지거나 auth 값이 잘못 만들어지면 pull·push 가 인증 오류로 실패하고, Kubernetes 에서는 같은 내용을 담은 kubernetes.io/dockerconfigjson 시크릿이 말없이 동작하지 않는다. 진단 순서를 정리한다.
{
"auths": {
"registry.example.com": {
"auth": "BASE64(사용자명:비밀번호)"
}
}
}
auth 는 사용자명:비밀번호 를 base64 로 한 번 인코딩한 값이다. 암호화가 아니라 인코딩이므로 이 파일은 평문 비밀번호와 같다고 보고 권한을 600 으로 둔다. 자격증명 헬퍼(credsStore)를 쓰면 auth 대신 헬퍼 이름만 남는다.
python3 -m json.tool ~/.docker/config.json
흔한 원인은 마지막 항목 뒤의 쉼표, 홑따옴표, 그리고 Windows 에서 만들어 옮길 때 붙는 BOM 이다.
file ~/.docker/config.json # UTF-8 (with BOM) 이면 문제
sed -i '1s/^\xEF\xBB\xBF//' ~/.docker/config.json
echo '<auth 값>' | base64 -d
사용자명:비밀번호 형태가 나와야 한다. 다음이 흔한 실패다.
echo 에 -n 을 빼서 개행이 섞여 들어간 경우. 반드시 echo -n 'user:pass' | base64 로 만든다.data 필드가 이미 base64 이므로 config.json 안의 값을 한 번 더 인코딩하면 두 겹이 된다.=)이 잘려 invalid input 이 나는 경우.원인을 파고들기보다 다시 만드는 편이 빠를 때가 많다.
mv ~/.docker/config.json ~/.docker/config.json.bak
docker login <레지스트리>
손으로 base64 를 다루지 말고 명령으로 만든다. 실수가 줄고 형식이 보장된다.
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=<사용자> \
--docker-password="${REGISTRY_PASSWORD}" \
-n <네임스페이스>
이미 만들어 둔 config.json 을 그대로 쓸 때는 파일에서 읽는다.
kubectl create secret generic regcred \
--from-file=.dockerconfigjson=config.json \
--type=kubernetes.io/dockerconfigjson
시크릿은 네임스페이스마다 따로 있어야 하고, 파드 스펙의 imagePullSecrets 에 이름을 적거나 서비스 어카운트에 붙여야 적용된다.
docker login http://호스트:포트 처럼 스킴을 붙이면 클라이언트가 URL 로 해석해 엉뚱하게 HTTPS 를 시도한다. 스킴 없이 호스트:포트 만 적고, 데몬에는 insecure-registries 를 등록한다. 설정은 Docker private registry insecure 설정 에 있다. 설정을 마쳤는데도 connection refused 가 그대로면 인증 문제가 아니라 레지스트리가 그 포트에서 듣고 있지 않은 것이다.