In the 17.0.6 docker engine update, the -e and --email flags were deprecated. Sending the -e flag now results in a 400 error. The client should attempt to check the docker version or re-try without the email flag if it fails. This is a breaking change in the docker application, and should be fixed as soon as possible.
https://docs.docker.com/engine/deprecated/#-e-and---email-flags-on-docker-login
Originally encountered this issue with
$(aws ecr get-login)
This calls:
docker login -u AWS -p <TOKEN> -e none <ECR_URL>
I'm not actually sure how this is related to the Python SDK.
I don't think this is related to docker-py; w.r.t. the command-line; the -e / --email option was deprecated for more than a year. The AWS team did make changes to adapt to this deprecation, but decided to default to the deprecated option, and require the user to set an additional --no-include-email to skip the deprecated option; see https://github.com/aws/aws-cli/blob/9417311ddf284eaa02155aff850dd90b3e5d2c43/awscli/customizations/ecr.py#L49-L55
Does it work if you $(was ecr get-login --no-include-email)?
Sorry, shouldn't have included the ecr bit in the issue. That was just how I was first made aware of the deprecation. I was collecting the URL and token from the ecr python sdk, and then using docker-py sdk to call docker login (not including an email field).
The code segment worked before upgrading to docker 17.0.6 yesterday, and then it stopped working. Calling the command line docker login with the token and URL from the python ECR command works fine.
This was the call I made. Using the same param values here in the command line worked fine, but failed in docker-py
docker.login(
username="AWS",
password=auth_data['authorizationToken'],
registry=auth_data['proxyEndpoint']
)
The error is:
docker.errors.APIError: 500 Server Error: Internal Server Error ("login attempt to https://<AWS_ID>.dkr.ecr.<REGION>.amazonaws.com/v2/ failed with status: 400 Bad Request")
any update here? The only way I can get around this right now is to login via the shell in a subprocess and then instantiate the APIClient
My suspicion is that the problem is here. The docker-py login command to log into a registry still passes an email parameter no matter what. This parameter was removed 17.0.6 and this is now an API error.
I'm, guessing that the expected behavior is that when no email parameter value is specified, the parameter will be dropped from the login request body.
I don't think that's the issue - requests are cleaned up and None values removed from the payload if present, see here
EDIT: As far as I can tell, that method is still conform to the current spec: https://docs.docker.com/engine/api/v1.32/#operation/SystemAuth . I suppose it's an issue specifically with ECR? Is there any documentation on what they expect their auth to look like somewhere?
Yes, the email field is _deprecated_, but not removed; https://github.com/moby/moby/blob/b248de7e332b6e67b08a8981f68060e6ae629ccf/api/types/auth.go#L3-L22
Even if it was, sending should not produce an error;
The API uses an open schema model, which means server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer Docker daemons.
curl -v \
--unix-socket /var/run/docker.sock \
"http://localhost/v1.35/auth" \
-H "Content-Type: application/json" \
-d '{"password":"foobar","serveraddress":"https://index.docker.io/v1/","username":"thajeztah","email":"[email protected]"}'
* Trying /var/run/docker.sock...
* Connected to localhost (/Users/sebastiaan/Library/Containers/com.dock) port 80 (#0)
> POST /v1.35/auth HTTP/1.1
> Host: localhost
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 108
>
* upload completely sent off: 108 out of 108 bytes
< HTTP/1.1 200 OK
< Api-Version: 1.35
< Content-Length: 48
< Content-Type: application/json
< Date: Thu, 21 Dec 2017 15:52:35 GMT
< Docker-Experimental: true
< Ostype: linux
< Server: Docker/17.12.0-ce-rc3 (linux)
<
{"IdentityToken":"","Status":"Login Succeeded"}
* Connection #0 to host localhost left intact
One thing I _do_ notice, is that the 400 error coming from ECS is converted into a 500 error by the Docker API, which should be corrected
I had the same issue until I realized that the tokens are base64 encoded - RTFM fail :(.
session = boto3.Session()
ecr = session.client('ecr')
login = ecr.get_authorization_token()
b64token = login['authorizationData'][0]['authorizationToken'].encode('utf-8')
username, password = base64.b64decode(b64token).decode('utf-8').split(':')
registry = login['authorizationData'][0]['proxyEndpoint']
client = docker.from_env()
client.login(username, password, registry=registry)
thanks @timwah that was it!
The workaround I used to login to aws docker repo.
aws ecr get-login -e none in the comand). Look for successful login output.cat ~/.docker/config.json to verify.
Most helpful comment
I had the same issue until I realized that the tokens are base64 encoded - RTFM fail :(.