LoginSignup
27
18

More than 3 years have passed since last update.

docker loginの認証はどこで実行されるか

Posted at

TL; DR

答えは、dockerコマンドを実行するOS/ユーザ です。

より詳細な仕組みを知りたい方は以下を読んでください。

dockerコマンドは3種類ある

はじめに docker コマンドは一つでないという話からはじめます。
ホストOSがLinux以外の場合、
dockerデーモンは仮想OS (macOSならHyperKit, WindowsならHyper-VまたはWSL2)上のLinuxで実行されています。

dockerコマンドは以下の三ヶ所から呼び出すことができます

  • ホストOS
  • 仮想OS
  • コンテナ内部(ソケットマウント方式でdocker in dockerしている場合)

docker (4).png

それぞれで実行されるdockerコマンドは実行されるOS上の普通のプログラムで、
dockerデーモンに対して通信をすることで実際のコンテナを実行します。

つまり、ホストOS上のdockerコマンドと仮想OS上のdockerコマンドは
全く別のバイナリということになります。(当たり前ですが)

docker login

docker login はDocker HubやGCR, ECRなどのコンテナレジストリにログインするコマンドです。
ログインすることで、コンテナのpushやprivate レポジトリからのpullができるようになります。

さてログイン処理はどのように実行されるのでしょうか。筆者が調べた限りでは以下のような仕様のようです。

  • (dockerデーモンではなく)dockerコマンドを実行したOSで実行される
  • 認証情報(の設定)は $HOME/.docker/config.json に保存される。

したがって以下のことに気をつける必要があります。

  1. ホストOS上でログイン状態は、root以外の別のユーザあるいは仮想OS上あるいはコンテナ内のdockerからは利用できません。

    • ホストOS上でdocker loginしておいても、 仮想OS上のdockerからその認証情報を用いたpush/pullはできません。
    • ホストOS上の別ユーザからもpush/pullはできません。(例外としてsudoによるpush/pullは可能です。これはsudoでは環境変数(特に$HOME)がユーザのものが引き継がれ、かつrootは~/.docker/config.jsonが読み出し可能だからです。)
      • OK: sudo docker pull ${private_image}
      • NG: echo docker pull ${private_image} | sudo su root
  2. docker loginコマンドをsudoで実行すると$HOME/.docker/config.jsonの所有者がrootとなります。
    ドキュメントには sudo docker loginした場合は /root/.docker/config.jsonに保存されると書いてありますが、少なくともmacOS上では $HOME/.docker/config.jsonに保存されることを確認しました。)

credential helper

docker loginの認証状態をいい感じに管理してくれるのがcredential helperと呼ばれるプログラムです。
これを使うと、docker loginのパスワードをOSのキーチェーンツールに保存したり、
AWSやGCPの認証コマンドを用いる事ができます。

~/.docker/config.jsonに設定を書くと利用できます。以下の例ではデフォルトのhelperとして
desktopを使い、gcr.ioなど特定のサイトでは gloudを使うという設定です。

{
    "credsStore": "desktop",
    "credHelpers": {
        "asia.gcr.io": "gcloud",
        "eu.gcr.io": "gcloud",
        "gcr.io": "gcloud",
        "marketplace.gcr.io": "gcloud",
        "staging-k8s.gcr.io": "gcloud",
        "us.gcr.io": "gcloud"
    }
}

credential helperはdocker-credential-のprefixがついた普通のプログラムです。

$ docker-credential-
docker-credential-desktop      docker-credential-gcloud       docker-credential-osxkeychain  

仕組みも非常に簡単で、引数にget、標準入力にログインしたいレポジトリのURLを渡すと認証情報を返してくれます。

$ echo https://gcr.io | docker-credential-gcloud get
{
  "Secret": "{ここは認証トークンなのでマスクしました}",
  "Username": "_dcgcloud_token"
}

したがって、こちらの設定・状態もdockerコマンドを実行するOSやユーザごとに独立しています。

docker in dockerで認証情報を共有したい場合

上記の理由から、dockerの認証情報は実行OS,ユーザごとに独立であるという事がわかりました。
したがって、docker in dockerを実現したい場合に、ホストLinuxの認証情報を共有した場合は
以下のようにする必要があります。

  1. コンテナ実行時に$HOME環境変数を適切に設定します。
  2. credential helperコンテナ内部のPATH上にマウントします
    -v $(which docker-credential-gloud:/usr/local/bin/docker-credential-gcloud)
  3. ホストOSの$HOME/.docker/config.jsonをコンテナ内にマウントします。
  4. credential helperが使う認証情報をコンテナ内部からアクセスできるようにします。(環境変数で渡すか鍵ファイルをマウントします)
27
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
18