npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

docker-registry-client-extended

v3.3.2

Published

node.js client for the Docker Registry API with some sprinklers

Downloads

426

Readme

node-docker-registry-client [EXTENDED]

A Docker Registry API client for node.js.

Limitations: Currently only support for Registry API v1 (https://docs.docker.com/v1.6/reference/api/registry_api/) pull support (i.e. excluding API endpoints for push) and Registry API v2 pull support. Support for v2 push endpoints is coming.

Note: This repository is part of the Joyent Triton project. See the contribution guidelines and general documentation at the main Triton project page.

Install

npm install docker-registry-client-extended

Overview

Most usage of this package involves creating a Registry API client for a specific repository and calling its methods.

A Registry client requires a repository name (called a repo in the code):

[INDEX/]NAME                # a "repo name"

Examples:

mongo                       # implies default index (docker.io) and namespace (library)
docker.io/mongo             # same thing
docker.io/library/mongo     # same thing

myreg.example.com:5000/busybox   # a "busybox" repo on a private registry

quay.io/trentm/foo          # trentm's "foo" repo on the quay.io service

The parseRepo function is used to parse these. See "examples/parseRepo.js" to see how they are parsed:

$ node examples/parseRepo.js mongo
{
    "index": {
        "name": "docker.io",
        "official": true
    },
    "official": true,
    "remoteName": "library/mongo",
    "localName": "mongo",
    "canonicalName": "docker.io/mongo"
}

Commonly, a "repo name and tag" string is used for working with a Docker registry, e.g. docker pull busybox:latest. The v2 API adds support for using "repo name and digest" to stably identify images, e.g. docker pull alpine@sha256:fb9f16730ac6316afa4d97caa5130219927bfcecf0b0ce35c01dcb612f449739. This package provides a parseRepoAndRef (and the synonym parseRepoAndTag) for that, e.g.:

$ node examples/parseRepoAndRef.js myreg.example.com:5000/busybox:foo
{
    "index": {
        "name": "myreg.example.com:5000",
        "official": false
    },
    "official": false,
    "remoteName": "busybox",
    "localName": "myreg.example.com:5000/busybox",
    "canonicalName": "myreg.example.com:5000/busybox",
    "tag": "foo"
}

Slightly different than docker.git's parsing, this package allows the scheme to be given on the index:

$ node examples/parseRepoAndRef.js https://quay.io/trentm/foo
{
    "index": {
        "scheme": "https",              // <--- scheme
        "name": "quay.io",
        "official": false
    },
    "official": false,
    "remoteName": "trentm/foo",
    "localName": "quay.io/trentm/foo",
    "canonicalName": "quay.io/trentm/foo",
    "tag": "latest"                     // <--- default to 'latest' tag
}

If a scheme isn't given, then "https" is assumed.

Usage

If you know, for example, that you are only dealing with a v2 Docker Registry, then simple usage will look like this:

var drc = require('docker-registry-client-extended');
var REPO = 'alpine';
var client = drc.createClientV2({name: REPO});

client.listTags(function (err, tags) {
    // ...
    console.log(JSON.stringify(tags, null, 4));

    /*
     * Because the client is typically using Keep-Alive, it will maintain
     * open connections. Therefore you should call `.close()` to close
     * those when finished.
     */
    client.close();
});

A more complete example (showing logging, auth, etc.):

var bunyan = require('bunyan');
var drc = require('docker-registry-client-extended');

// This package uses https://github.com/trentm/node-bunyan for logging.
var log = bunyan.createLogger({
    name: 'regplay',
    // TRACE-level logging will show you all request/response activity
    // with the registry. This isn't suggested for production usage.
    level: 'trace'
});

var REPO = 'alpine';
var client = drc.createClientV2({
    name: REPO,
    log: log,
    // Optional basic auth to the registry
    username: <username>,
    password: <password>,
    // Optional, for a registry without a signed TLS certificate.
    insecure: <true|false>,
    // ... see the source code for other options
});

This package also supports the nominal technique for pinging the registry to see if it supports v2, otherwise falling back to v1:

var drc = require('docker-registry-client-extended');

var REPO = 'alpine';
drc.createClient({name: REPO, /* ... */}, function (err, client) {
    console.log('Got a Docker Registry API v%d client', client.version);
    // ...
});

v2 API

A mapping of the Docker Registry API v2 endpoints to the API equivalents in this client lib. "NYI" means the endpoint is not yet implemented by this client lib.

| Name | Endpoint | Description | | -------------------- | -------- | ----------- | | ping | GET /v2/ | Check that the endpoint implements Docker Registry API V2. | | listTags | GET /v2/<name>/tags/list | Fetch the tags under the repository identified by name. | | getManifest | GET /v2/<name>/manifests/<reference> | Fetch the manifest identified by name and reference where reference can be a tag or digest. | | putManifest | PUT /v2/<name>/manifests/<reference> | NYI. Put the manifest identified by name and reference where reference can be a tag or digest. | | deleteManifest | DELETE /v2/<name>/manifests/<reference> | NYI. Delete the manifest identified by name and reference where reference can be a tag or digest. | | createBlobReadStream | GET /v2/<name>/blobs/<digest> | Retrieve the blob from the registry identified by digest. | | headBlob | HEAD /v2/<name>/blobs/<digest> | Retrieve the blob from the registry identified by digest -- just the headers. | | startBlobUpload | POST /v2/<name>/blobs/uploads/ | NYI. Initiate a resumable blob upload. If successful, an upload location will be provided to complete the upload. Optionally, if the digest parameter is present, the request body will be used to complete the upload in a single request. | | getBlobUploadStatus | GET /v2/<name>/blobs/uploads/<uuid> | NYI. Retrieve status of upload identified by uuid. The primary purpose of this endpoint is to resolve the current status of a resumable upload. | | uploadBlobChunk | PATCH /v2/<name>/blobs/uploads/<uuid> | NYI. Upload a chunk of data for the specified upload. | | completeBlobUpload | PUT /v2/<name>/blobs/uploads/<uuid> | NYI. Complete the upload specified by uuid, optionally appending the body as the final chunk. | | cancelBlobUpload | DELETE /v2/<name>/blobs/uploads/<uuid> | NYI. Cancel outstanding upload processes, releasing associated resources. If this is not called, the unfinished uploads will eventually timeout. | | deleteBlob | DELETE /v2/<name>/blobs/<digest> | NYI. Delete the blob identified by name and digest. Warning: From the Docker spec I'm not sure that deleteBlob doesn't corrupt images if you delete a shared blob. | | listRepositories | GET /v2/_catalog/ | NYI List all repositories in this registry. Spec. |

See "examples/v2/*.js" for short code examples one can run from the CLI for each API endpoint. E.g.:

$ npm install   # install dependencies for this module
$ node examples/v2/listTags.js busybox
{
    "name": "library/busybox",
    "tags": [
        "buildroot-2013.08.1",
        "buildroot-2014.02",
        "latest",
        "ubuntu-12.04",
        "ubuntu-14.04"
    ]
}

You can also get logging on processing and HTTP requests/responses via the -v option to the example scripts. This library uses Bunyan for logging, so you'll want to pipe the log output (on stderr) through the bunyan command for pretty output:

$ node examples/v2/listTags.js -v busybox 2>&1 | ./node_modules/.bin/bunyan
[2015-06-01T22:26:44.065Z] TRACE: v2.listTags/registry/23400 on grape.local: request sent
    GET /v2/ HTTP/1.1
    Host: registry-1.docker.io
    accept: application/json
    user-agent: node-docker-registry-client/2.0.0 (x64-darwin; node/0.10.28)
    date: Mon, 01 Jun 2015 22:26:44 GMT
[2015-06-01T22:26:44.480Z] TRACE: v2.listTags/registry/23400 on grape.local: Response received (client_res={})
    HTTP/1.1 401 Unauthorized
    content-type: application/json; charset=utf-8
    docker-distribution-api-version: registry/2.0
    www-authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io"
    date: Mon, 01 Jun 2015 22:26:44 GMT
    content-length: 114
    connection: close
    strict-transport-security: max-age=3153600
[2015-06-01T22:26:44.482Z] TRACE: v2.listTags/registry/23400 on grape.local:
    body received:
    {"errors":[{"code":"UNAUTHORIZED","message":"access to the requested resource is not authorized","detail":null}]}
[2015-06-01T22:26:44.485Z] TRACE: v2.listTags/registry/23400 on grape.local: login
[2015-06-01T22:26:44.487Z] DEBUG: v2.listTags/registry/23400 on grape.local: login: get Bearer auth token
...
[2015-06-01T22:26:45.680Z] TRACE: v2.listTags/registry/23400 on grape.local:
    body received:
    {"name":"library/busybox","tags":["buildroot-2013.08.1","buildroot-2014.02","latest","ubuntu-12.04","ubuntu-14.04"]}
{
    "name": "library/busybox",
    "tags": [
        "buildroot-2013.08.1",
        "buildroot-2014.02",
        "latest",
        "ubuntu-12.04",
        "ubuntu-14.04"
    ]
}

v1 API

A mapping of the Docker Registry API v1 endpoints to the API equivalents in this client lib.

Limitation: Only the read endpoints of the v1 API are implement. I.e. putting layers, deleting repositories, setting/deleting tags are all not implemented.

| Name | Endpoint | Description | | ----------------- | -------- | ----------- | | ping | GET /v1/_ping | Check status of the registry. | | search | GET /v1/search | Search the index. | | listRepoImgs | GET /v1/repositories/$repo/images | List all images in this repo. This is actually against the "Index API" (aka "Hub API"). | | listRepoTags | GET /v1/repositories/$repo/tags | List all tags for a repo. | | getImgAncestry | GET /v1/images/$imgId/ancestry | Get the ancestry of an image. | | getImgJson | GET /v1/images/$imgId/json | Get the metadata (sometimes called the "image JSON") for an image. | | getImgLayerStream | GET /v1/images/$imgId/layer | Download the image layer file. | | - | PUT /v1/images/$imgId/layer | Not implemented. Put image layer. | | - | DELETE /v1/repositories/$repo/tags/$tag | Not implemented. Delete a repo tag. | | - | PUT /v1/repositories/$repo/tags/$tag | Not implemented. Set a repo tag. | | - | DELETE /v1/repositories/$repo | Not implemented. Delete a repo. |

See "examples/v1/*.js" for short code examples one can run from the CLI for each API endpoint. E.g.:

$ npm install   # install dependencies for this module
$ node examples/v1/listRepoTags.js busybox
{
    "buildroot-2013.08.1": "3dba22db9896eb5f020691e1f8cda46735de533ca7b6b1b3b072272752935bad",
    "buildroot-2014.02": "8c2e06607696bd4afb3d03b687e361cc43cf8ec1a4a725bc96e39f05ba97dd55",
    "latest": "8c2e06607696bd4afb3d03b687e361cc43cf8ec1a4a725bc96e39f05ba97dd55",
    "ubuntu-12.04": "faf804f0e07b2936e84c9fe4ca7c60a6246cc669cf2ff70969f14a9eab6efb48",
    "ubuntu-14.04": "32e97f5f5d6bd15b9cc293b38a5102a7ddac736852811110043992b20553177a"
}

You can also get logging on processing and HTTP requests/responses via the -v option to the example scripts. This library uses Bunyan for logging, so you'll want to pipe the log output (on stderr) through the bunyan command for pretty output:

$ node listRepoTags.js -v busybox 2>&1 | bunyan
[2015-09-02T22:14:35.790Z] TRACE: listRepoTags/registry/13388 on danger0.local: get session token/cookie
[2015-09-02T22:14:35.836Z] TRACE: listRepoTags/registry/13388 on danger0.local: request sent
    GET /v1/repositories/library/busybox/images HTTP/1.1
    Host: index.docker.io
    X-Docker-Token: true
    accept: application/json
    user-agent: node-docker-registry-client/2.0.0 (x64-darwin; node/0.10.40)
    date: Wed, 02 Sep 2015 22:14:35 GMT
[2015-09-02T22:14:36.374Z] TRACE: listRepoTags/registry/13388 on danger0.local: Response received (client_res={})
    HTTP/1.1 200 OK
    server: nginx/1.6.2
    date: Wed, 02 Sep 2015 22:14:36 GMT
...
[2015-09-02T22:14:37.888Z] TRACE: listRepoTags/registry/13388 on danger0.local:
    body received:
    {"buildroot-2013.08.1": "3dba22db9...
[2015-09-02T22:14:37.888Z] TRACE: listRepoTags/registry/13388 on danger0.local: close http client (host=index.docker.io)
[2015-09-02T22:14:37.889Z] TRACE: listRepoTags/registry/13388 on danger0.local: close http client (host=registry-1.docker.io)
{
    "buildroot-2013.08.1": "3dba22db9896eb5f020691e1f8cda46735de533ca7b6b1b3b072272752935bad",
    "buildroot-2014.02": "8c2e06607696bd4afb3d03b687e361cc43cf8ec1a4a725bc96e39f05ba97dd55",
    "latest": "8c2e06607696bd4afb3d03b687e361cc43cf8ec1a4a725bc96e39f05ba97dd55",
    "ubuntu-12.04": "faf804f0e07b2936e84c9fe4ca7c60a6246cc669cf2ff70969f14a9eab6efb48",
    "ubuntu-14.04": "32e97f5f5d6bd15b9cc293b38a5102a7ddac736852811110043992b20553177a"
}

V1 client usage:

var repo = 'alpine';
var client = drc.createClientV1({
    name: repo,
    // ...
});
client.listRepoTags(function (err, repoTags) {
    client.close();
    if (err) {
        console.log(err);
        process.exit(1);
    }
    console.log(JSON.stringify(repoTags, null, 4));
});

Development

Naming convensions

For naming this package attempts to consistently use repo for repository, img for image, etc.

Commits

Before commit, ensure that the following checks are clean:

make prepush

Releases

Changes with possible user impact should:

  1. Add a note to the changelog (CHANGES.md).

  2. Bump the package version appropriately.

  3. Once merged to master, the new version should be tagged and published to npm via:

     make cutarelease

    To list to npm accounts that have publish access:

     npm owner ls docker-registry-client

The desire is that users of this package use published versions in their package.json dependencies, rather than depending on git shas.