AgustinCB / docker-api

Docker Remote API driver for node.js. It uses the same modem than dockerode, but the interface is promisified and with a fancier syntax.
GNU General Public License v3.0
302 stars 51 forks source link

login method? #36

Open cyrfer opened 6 years ago

cyrfer commented 6 years ago

I must be overlooking it, but I cannot find the equivalent to docker login in the SDK.

I need to use docker login because I am trying to pull an image that exists in AWS ECR. I found the pull command in this SDK,

docker.image.create(...)

I found that I can get a session token from ECR using ecr.getAuthorizationToken. http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/ECR.html#getAuthorizationToken-property

How can I use the token from ECR with docker login in your SDK?

Update: After more searching, I found the docker endpoint called /auth but now I am wondering how to pass it the authentication Token from ECR. https://docs.docker.com/engine/api/v1.24/#33-misc

Update 2: I found in the docker api v 1.33 they support an identitytoken that seems like the right place to put the token from ECR. https://docs.docker.com/engine/api/v1.33/#section/Authentication

Update 3: Piecing together the docs I have this code:

const promisifyAwsResponse = (awsResponse) => new Promise((resolve, reject) => {
    awsResponse.on('success', (res) => {
        console.log('awsResponse success:', JSON.stringify(res.data));
        resolve(res.data);
    });
    awsResponse.on('error', (err) => {
        console.error('awsResponse error:', err);
        reject(err);
    });
    awsResponse.send();
});

    const ecrParams = {
    };
    return promisifyAwsResponse(ECR.getAuthorizationToken(ecrParams))
        .then((ecrAuthResult) => {
            const ecrAuth = ecrAuthResult.authorizationData[0];
            // I just realized the first arg is for auth data
            return docker.image.create({
                    identitytoken: ecrAuth.authorizationToken,
                    serveraddress: ecrAuth.proxyEndpoint
                }, {
                    fromImage: "ecrImageName",
                    tag: 'latest'
                });
        })
      .catch((err) => console.error(err));

Unfortunately I get the same error as when I make no attempt to authenticate with ECR.

Error: (HTTP code 500) server error - Get https://omittedAccount.dkr.ecr.us-west-2.amazonaws.com/v2/omittedRepoName/manifests/latest: no basic auth credentials"
cyrfer commented 6 years ago

@AgustinCB is this related to #24 in that there might be a bug or is it simply developer-usage-error?

AgustinCB commented 6 years ago

I'm sorry, I'm not really familiar with the AWS that you're trying to use.

The equivalent of the login command in the docker cli would be auth: https://github.com/AgustinCB/docker-api/blob/master/test/docker.js#L27

Is that what you're looking for?

I won't be free till the weekend, will take a look on Saturday to see if I understand how AWS ECR works and how to integrate with this library.

Sorry I can't be more helpful right now!

cyrfer commented 6 years ago

No rush. I think these are the relevant docs

I am might avoid passing auth tokens into the docker api by installing a Docker Credential Helper.

AgustinCB commented 6 years ago

OK, based on a quick learn over their page, I'd try this:

const promisifyAwsResponse = (awsResponse) => new Promise((resolve, reject) => {
    awsResponse.on('success', (res) => {
        console.log('awsResponse success:', JSON.stringify(res.data));
        resolve(res.data);
    });
    awsResponse.on('error', (err) => {
        console.error('awsResponse error:', err);
        reject(err);
    });
    awsResponse.send();
});

    const ecrParams = {
    };
    return promisifyAwsResponse(ECR.getAuthorizationToken(ecrParams))
        .then((ecrAuthResult) => {
            const ecrAuth = ecrAuthResult.authorizationData[0];
            // I just realized the first arg is for auth data
            return docker.auth({
              username: "AWS",
              password: ecrAuth.authorizationToken,
              serveraddress: ecrAuth.proxyEndpoint
            }).then((resp) =>
              docker.image.create({
                  identitytoken: resp.IdentityToken,
                  serveraddress: ecrAuth.proxyEndpoint
              }, {
                  fromImage: "ecrImageName",
                  tag: 'latest'
              })
           )
        })
      .catch((err) => console.error(err));

I'm basing this on this endpoint of the API: https://docs.docker.com/engine/api/v1.31/#operation/SystemAuth (which is the auth method) and in the document you sent me.

Keep in mind: I'm not able to test this, so there might be syntax errors in my code.

cyrfer commented 6 years ago

That looks right, but when I used this code I still did not succeed. The new error was malformed request to docker auth. I am going back to the drawing board. If someone figures it out, it would be a cool demo of your SDK.

AgustinCB commented 6 years ago

Which version of docker are you running?

cyrfer commented 6 years ago

17.09.0-ce-mac35

AgustinCB commented 6 years ago

I'm currently working on trying to make this work :). Will come back to you

sobiso commented 6 years ago

Any news about this case?

gbhrdt commented 5 years ago

For anyone looking for a solution, this post from the dockerode community also works with this library:

https://github.com/apocas/dockerode/issues/448#issuecomment-384801924

wanseob commented 4 years ago

For anyone looking for a solution, this post from the dockerode community also works with this library:

apocas/dockerode#448 (comment)

Thank you so much. This saved my day.