dockerのcredsStoreの仕組みとサンプル実装

## jsonの中身

```json:~/.docker/config.json
{
        "credsStore": "dev-containers-xxxx-xxxx-xxxx-xxxx-xxxx"
}
```

## credsStoreが生きてるか確認する方法

```sh
CREDS_STORE=$(cat ~/.docker/config.json | jq '.credsStore' --raw-output);
docker-credential-$CREDS_STORE version
```

こんな感じで `docker-credential-` の後にcredsStoreの名前が繋がります.

以下の例はmacbookでdocker for macを利用した場合です

```json:~/.docker/config.json
{
        "credsStore": "desktop"
}
```

基本的に以下のコマンドが利用可能です.

```
$ docker-credential-$(cat ~/.docker/config.json | jq '.credsStore' --raw-output) -h
Usage:
  docker-credential-desktop [flags]
  docker-credential-desktop [command]

Available Commands:
  completion  Generate the autocompletion script for the specified shell
  erase       Removes a set of credentials from the store
  get         Retrieves credentials from the store
  help        Help about any command
  list        Lists the credentials in the store
  store       Adds a set of credentials to the store
  version     Display the version of the credentials helper protocol

Flags:
  -h, --help   help for docker-credential-desktop

Use "docker-credential-desktop [command] --help" for more information about a command.
```

展開後のコマンドも置いておきます

```sh
$ docker-credential-desktop -h
Usage:
  docker-credential-desktop [flags]
  docker-credential-desktop [command]

Available Commands:
  completion  Generate the autocompletion script for the specified shell
  erase       Removes a set of credentials from the store
  get         Retrieves credentials from the store
  help        Help about any command
  list        Lists the credentials in the store
  store       Adds a set of credentials to the store
  version     Display the version of the credentials helper protocol

Flags:
  -h, --help   help for docker-credential-desktop

Use "docker-credential-desktop [command] --help" for more information about a command.
```

## credsStoreの実装例

理解を深める為の動作する例です.

```python
#!/usr/bin/env python3

import sys
import json
import os

CREDENTIALS_FILE = os.path.expanduser('~/.docker/simple_creds_store.json')

def get_input():
    input_data = sys.stdin.read().strip()
    try:
        return json.loads(input_data)
    except json.JSONDecodeError:
        return {"ServerURL": input_data}

def store_credentials(server_url, username, secret):
    if not os.path.exists(CREDENTIALS_FILE):
        with open(CREDENTIALS_FILE, 'w') as f:
            json.dump({}, f)

    with open(CREDENTIALS_FILE, 'r') as f:
        credentials = json.load(f)

    credentials[server_url] = {
        'Username': username,
        'Secret': secret
    }

    with open(CREDENTIALS_FILE, 'w') as f:
        json.dump(credentials, f)

def get_credentials(server_url):
    if not os.path.exists(CREDENTIALS_FILE):
        return {}

    with open(CREDENTIALS_FILE, 'r') as f:
        credentials = json.load(f)

    return credentials.get(server_url, {})

def delete_credentials(server_url):
    if not os.path.exists(CREDENTIALS_FILE):
        return

    with open(CREDENTIALS_FILE, 'r') as f:
        credentials = json.load(f)

    if server_url in credentials:
        del credentials[server_url]

    with open(CREDENTIALS_FILE, 'w') as f:
        json.dump(credentials, f)

def list_credentials():
    if not os.path.exists(CREDENTIALS_FILE):
        return {}

    with open(CREDENTIALS_FILE, 'r') as f:
        credentials = json.load(f)
    
    return credentials

def main():
    command = sys.argv[1]

    if command == 'store':
        input_data = get_input()
        store_credentials(input_data['ServerURL'], input_data['Username'], input_data['Secret'])
    elif command == 'get':
        input_data = get_input()
        result = get_credentials(input_data['ServerURL'])
        if result:
            print(json.dumps(result))
    elif command == 'erase':
        input_data = get_input()
        delete_credentials(input_data['ServerURL'])
    elif command == 'list':
        result = list_credentials()
        if result:
            print(json.dumps(list(result.keys())))
        else:
            print(json.dumps([]))

if __name__ == '__main__':
    main()
```

`docker-credential-simple-store` コマンドを使えるようにします

```sh
chmod +x docker-credential-simple-store.py
sudo cp docker-credential-simple-store.py /usr/local/bin/docker-credential-simple-store
```

作成した `docker-credential-simple-store` コマンドをdockerで利用してもらうようにします.

```json:~/.docker/config.json
{
        "credsStore": "simple-store"
}
```

実際に使用する例です

```sh
# 資格情報の保存
echo '{"ServerURL": "example.com", "Username": "myuser", "Secret": "mypassword"}' | docker-credential-simple-store store

# 資格情報の取得
echo '{"ServerURL": "example.com"}' | docker-credential-simple-store get

# 資格情報の一覧
docker-credential-simple-store list

# 資格情報の削除　
echo '{"ServerURL": "example.com"}' | docker-credential-simple-store erase

# docker hubにログイン
docker login
docker-credential-simple-store list
```