Search code examples
windowsamazon-web-servicesdockeramazon-ecs

Docker push to AWS ECR fails on Windows: no basic auth credentials


I am using docker on windows (Docker for Windows, not Docker Toolbox) and aws cli in cygwin ("git bash") shell. I'm trying to push a docker image into AWS ECR - the private ECS repository.

Whatever I do - when I'm running docker push I repeatedly get:

no basic auth credentials

Method 1

I have been following instructions and running the standard commands:

$ $(aws --profile myprofile ecr get-login --region us-east-1)
Login Succeeded
$ docker tag myrepo:latest 123456789.dkr.ecr.us-east-1.amazonaws.com/myrepo:latest
$ docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/myrepo:latest
The push refers to a repository [232097583865.dkr.ecr.us-east-1.amazonaws.com/potion]
688f61a6956d: Preparing
11908ead416e: Preparing
no basic auth credentials

No success.

Trying to pull reveals that indeed, I don't have access:

$ docker pull 123456789.dkr.ecr.us-east-1.amazonaws.com/myrepo
Using default tag: latest
Pulling repository 123456789.dkr.ecr.us-east-1.amazonaws.com/myrepo
unauthorized: authentication required

However docker does think that I'm logged in:

$ docker logout https://123456789.dkr.ecr.us-east-1.amazonaws.com
Remove login credentials for https://123456789.dkr.ecr.us-east-1.amazonaws.com

# let's run again - should not be logged in now
$ docker logout https://123456789.dkr.ecr.us-east-1.amazonaws.com
Not logged in to https://123456789.dkr.ecr.us-east-1.amazonaws.com

Hmm.

Method 2

Internet suggests dissecting the command and using an older procedure to log on.

Basically boils down to something like this:

docker login -u AWS -p $(aws --profile myprofile ecr get-authorization-token --region us-east-1 --output text --query authorizationData[].authorizationToken | python -c 'import base64, sys; print base64.b64decode(sys.stdin.read())' | cut -d: -f2) https://123456789.dkr.ecr.us-east-1.amazonaws.com

This also seems to succeed, but docker push or pull result in the same failure.

Other Dead Ends

Windows and cygwin is weird. So, let's put the docker login command in a shell script file, and run it, or source it. No success.

Generating additional AMI profiles with explicit access tokens and new sets of credentials. No success.

Exporting the AWS credentials as environment variables and repeating the process. No success.

Using the awesome aws-temp-token.sh script that takes an MFA code and generates session credentials as environment variables. No success (though the tool is a life saver at other times, so use it).

Spoiler Alert

I did eventually manage to solve this problem. It was so frustrating though and I found no online mention of the solution, so writing an answer should hopefully relieve some of the mental pain.


Solution

  • One of my searches led me to this answer, which while irrelevant to my case, brought to my attention the place where authentication credentials are stored: the docker config.json file. Take a look here to read more about it and its auth usage.

    However, my own file had these contents after logging in with any of the methods above:

    {
        "auths": {
            "https://123456789.dkr.ecr.us-east-1.amazonaws.com": {}
        },
        "credsStore": "wincred"
    }
    

    The explicit mention of Windows (wincred) caught my attention. Reading more into this, it appears docker on Windows uses a helper credential store which is probably better than storing credentials as plain text on the file system (it's normally stored as base64 which is greek for "plain text").

    However - the solution came when I manually edited this file to contain the authentication token directly.

    I generated my authentication token with this command (output shortened for brevity):

    $ aws --profile myprofile ecr get-authorization-token --region us-east-1 --output text --query authorizationData[].authorizationToken
    jFHNnVxZ............Vqc==
    

    After editing ~/.docker/config.json, it looked something like this:

    {
        "auths": {
            "https://123456789.dkr.ecr.us-east-1.amazonaws.com": {
                "auth": "jFHNnVxZ............Vqc=="
            }
        }
    }
    

    And with this in place, the push is finally successful:

    $ docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/myrepo:latest
    The push refers to a repository [123456789.dkr.ecr.us-east-1.amazonaws.com/myrepo]
    61a69688f56d: Pushed
    11ad4908e16e: Pushed
    myrepo: digest: sha256:20c0f3......82aa19 size: 42162
    

    And all is well once more.