Docker Context

読む時間の目安: 4 分

はじめに

本ガイドでは コンテキスト(context)というものが、いかに簡単に、単一の Docker CLI から複数 Swarm クラスターを、そして複数 Kubernetes クラスター、各 Docker ノードを操作できるかを示します。

1 つの Docker CLI に対しては、複数のコンテキスト(context)を持たせることができます。 各コンテキストには、さまざまなクラスターやノードの管理に必要となる、エンドポイント情報やセキュリティ情報が含まれています。 docker contextコマンドを使うと、そういったコンテキストを簡単に設定したり切り替えたりすることができます。

その例として、会社で利用するノート PC 上において、1 つの Docker クライアントから 2 つのコンテキスト、dev-k8sprod-swarm の利用設定が必要であるとします。 dev-k8s は、開発環境上の Kubernetes クラスターの設定管理を行うものであり、エンドポイントデータやセキュリティ情報が含まれています。 一方 prod-swarm は、本番環境上の Swarm クラスター管理を一手に引き受けているものとします。 コンテキストの設定を一度行ってしまえば、トップレベルのコマンドdocker context use <コンテキスト名>を実行するだけで、コンテキストを簡単に切り替えられるようになります。

Docker Context を利用し、開発アプリをクラウド上にデプロイする方法については、Azure 上の Docker コンテナーのデプロイECS 上への Docker コンテナーのデプロイ を参照してください。

前提条件

本ガイドの利用例を進めていくためには、以下が必要になります。

  • トップレベルコマンドcontextをサポートしている Docker クライアント。

docker contextを実行して、Docker クライアントがコンテキストをサポートしていることを確認してください。

また以下のいずれかが必要です。

  • Docker Swarm クラスター
  • 単独エンジンによる Docker クラスター
  • Kubernetes クラスター

コンテキストの意味

コンテキストとは、複数プロパティが組み合わせれたものです。 そこには以下の情報が含まれます。

  • 名前
  • エンドポイント設定
  • TLS 情報
  • オーケストレーター

コンテキストというものがどのようなものに見えるかは、default コンテキストを見てみれば一番よくわかります。

$ docker context ls
NAME          DESCRIPTION     DOCKER ENDPOINT                KUBERNETES ENDPOINT      ORCHESTRATOR
default *     Current...      unix:///var/run/docker.sock                             swarm

上の結果より、「default」という単一のコンテキストがあることがわかります。 これは Swarm クラスターとやりとりするものとして設定されていて、ローカルの Unix ソケット/var/run/docker.sockを利用して実現するものとなっています。 ここには Kubernetes のエンドポイントは設定されていません。

NAME列の横に示されるアスタリスクは、そのコンテキストがアクティブであることを表わします。 これはつまりdockerコマンドがすべて、この「default」コンテキストに対して実行されることを意味します。 DOCKER_HOSTDOCKER_CONTEXTといった環境変数を使うか、コマンドラインから--context--hostフラグを指定することで、その対象をオーバーライドすることができます。

さらに詳しく見るにはdocker context inspectを実行します。 この例においては、defaultというコンテキストを確認しています。

$ docker context inspect default
[
    {
        "Name": "default",
        "Metadata": {
            "StackOrchestrator": "swarm"
        },
        "Endpoints": {
            "docker": {
                "Host": "unix:///var/run/docker.sock",
                "SkipTLSVerify": false
            }
        },
        "TLSMaterial": {},
        "Storage": {
            "MetadataPath": "\u003cIN MEMORY\u003e",
            "TLSPath": "\u003cIN MEMORY\u003e"
        }
    }
]

このコンテキストでは、オーケストレーター(metadata.stackOrchestrator)として「swarm」を利用しています。 また /var/run/docker.sockにあるローカル Unix ソケットを使い、利用可能なエンドポイントとの間でやりとりを行うように設定されています(Endpoints.docker.Host)。 そして TLS 検証を必要とする設定もあります(Endpoints.docker.SkipTLSVerify)。

新たなコンテキストの生成

新たなコンテキストを生成するにはdocker context createコマンドを実行します。

以下の例では「docker-test」というコンテキストを生成するものとし、以下を設定するものとします。

  • デフォルトのオーケストレーターを Swarm とします。
  • ローカル Unix ソケット/var/run/docker.sockに対してコマンド実行するものとします。
$ docker context create docker-test \
  --default-stack-orchestrator=swarm \
  --docker host=unix:///var/run/docker.sock

Successfully created context "docker-test"

新たなコンテキストは~/.docker/contexts/配下のmeta.json内に保存されます。 コンテキストを新規に生成すると、~/.docker/contexts/に専用のサブディレクトリが生成され、それぞれのmeta.jsonが保存されるものです。

メモ: デフォルトのコンテキストは、手動で生成したコンテキストとは、多少違った動きをします。 デフォルトのコンテキストには、設定ファイルmeta.jsonが存在しません。 そしてその時点の設定に基づいて、動的に設定が更新されます。 たとえばコマンドkubectl config use-contextを実行して、現在の Kubernetes 設定を切り替えたとします。 この場合 Docker のデフォルトコンテキストは、新たに Kubernetes エンドポイントに対応して、動的にコンテキスト自体を更新します。

新たに生成したコンテキストは、docker context lsdocker context inspect <コンテキスト名>により確認することができます。

以下のコマンドは新たな設定を生成するものであり、/home/ubuntu/.kube/configに保存されている既存の kubeconfig を使って、デフォルトのオーケストレーターを Kubernetes とする設定を行うものです。 これを動作させるためには、/home/ubuntu/.kube/configに Kubernetes の適切な設定ファイルが存在している必要があります。 kubeconfig に複数のコンテキストが設定されている場合、現在のコンテキスト(kubectl config current-context)が用いられます。

$ docker context create k8s-test \
  --default-stack-orchestrator=kubernetes \
  --kubernetes config-file=/home/ubuntu/.kube/config \
  --docker host=unix:///var/run/docker.sock

Successfully created context "k8s-test"

システム上にあるコンテキストをすべて確認するにはdocker context lsを実行します。

$ docker context ls
NAME           DESCRIPTION   DOCKER ENDPOINT               KUBERNETES ENDPOINT               ORCHESTRATOR
default *      Current       unix:///var/run/docker.sock   https://35.226.99.100 (default)   swarm
k8s-test                     unix:///var/run/docker.sock   https://35.226.99.100 (default)   kubernetes
docker-test                  unix:///var/run/docker.sock                                     swarm

カレントなコンテキストはアスタリスク(”*“)により示されます。

別のコンテキストへの切り替え

docker context useコマンドを利用すれば、コンテキストの切り替えをすばやく行うことができます。

以下のコマンドはdockerCLI が「k8s-test」コンテキストを利用するように切り替えるものです。

$ docker context use k8s-test

k8s-test
Current context is now "k8s-test"

処理結果を確認するため、コンテキストをすべて一覧表示して、「k8s-test」コンテキストにアスタリスク(”*“)がついているかどうかを見てみます。

$ docker context ls
NAME            DESCRIPTION                               DOCKER ENDPOINT               KUBERNETES ENDPOINT               ORCHESTRATOR
default         Current DOCKER_HOST based configuration   unix:///var/run/docker.sock   https://35.226.99.100 (default)   swarm
docker-test                                               unix:///var/run/docker.sock                                     swarm
k8s-test *                                                unix:///var/run/docker.sock   https://35.226.99.100 (default)   kubernetes

dockerコマンドはこれ以降、「k8s-test」コンテキストに定義されたエンドポイントを操作対象とします。

コンテキストの設定は、環境変数DOCKER_CONTEXTを使って行うこともできます。 これはdocker context useによって設定されたコンテキストをオーバーライドします。

以下の中から適切なコマンドを選んで、環境変数を利用したdocker-testコンテキストの設定を行います。

Windows PowerShell の場合

> $Env:DOCKER_CONTEXT=docker-test

Linux の場合

$ export DOCKER_CONTEXT=docker-test

docker context lsを実行すると、「docker-test」コンテキストが現在のアクティブコンテキストであることがわかります。

またグローバルな--contextフラグを使うとDOCKER_CONTEXT環境変数によるコンテキスト指定ををオーバーライドします。 たとえば以下は、コマンドに対して「production」というコンテキストを指定します。

$ docker --context production container ls

Docker Context のインポート、エクスポート

docker contextコマンドでは、Docker クライアントがインストールされている別のマシンにおいて、コンテキストを簡単にインポート、エクスポートすることができます。

docker context exportコマンドを使うと、既存のコンテキストをファイルにエクスポートします。 そのファイルは、dockerクライアントがインストールされている別のマシンにインポートすることができます。

デフォルトでコンテキストは ネイティブな Docker Context としてエクスポートされます。 これはdocker contextコマンドを使って、インポートエクスポートができるものです。 エクスポートしたコンテキストに Kubernetes エンドポイントが含まれている場合、その Kubernetes 部分のコンテキストも exportimport操作を通じて含まれることになります。

エクスポートにあたっては Kubernetes 部分のコンテキストだけをエクスポートすることもできます。 これにより、ネイティブな kubeconfig ファイルが生成され、そのファイル内容は、kubectlがインストールされている他のホスト上において~/.kube/configファイルへ手動でマージすることができます。 Kubernetes 部分のコンテキストだけをエクスポートし、これをインポートする場合は、docker context importコマンドは使えません。 エクスポートされた Kubernetes 設定をインポートするには、既存の kubeconfig ファイルに対して、手動でマージする以外に方法はありません。

ネイティブな Docker コンテキストのエクスポートとインポートを以降に示します。

ネイティブな Docker コンテキストのエクスポートとインポート

以下の例では「docker-test」という既存のコンテキストをエクスポートします。 これはコンテキストをdocker-test.dockercontextというファイルに出力します。

$ docker context export docker-test
Written file "docker-test.dockercontext"

エクスポートしたファイルの中身を確認します。

$ cat docker-test.dockercontext
meta.json0000644000000000000000000000022300000000000011023 0ustar0000000000000000{"Name":"docker-test","Metadata":{"StackOrchestrator":"swarm"},"Endpoints":{"docker":{"Host":"unix:///var/run/docker.sock","SkipTLSVerify":false}}}tls0000700000000000000000000000000000000000000007716 5ustar0000000000000000

このファイルは、別のホスト上においてdocker context importを使ってインポートできます。 対象とするホストには、Docker クライアントがインストールされている必要があります。

$ docker context import docker-test docker-test.dockercontext
docker-test
Successfully imported context "docker-test"

コンテキストがインポートできたかどうかはdocker context lsにより確認します。

インポートするコマンドの記述書式はdocker context import <コンテキスト名> <コンテキストファイル>です。

次は、コンテキストの Kubernetes 部分のみをエクスポートする例です。

Kubernetes コンテキストのエクスポート

Kubernetes コンテキストがエクスポートできるのは、エクスポートするコンテキスト内に Kubernetes エンドポイントが設定されている場合に限ります。 Kubernetes コンテキストのインポートにはdocker context importを使うことはできません。

この手順では--kubeconfigフラグを使って Kubernetes 部分のコンテキスト のみ をエクスポートします。 コンテキスト名は既存のk8s-testであり、これを「k8s-test.kubeconfig」というファイルに出力します。 catコマンドを実行すれば、適正な kubeconfig ファイルとして出力されていることがわかります。

$ docker context export k8s-test --kubeconfig
Written file "k8s-test.kubeconfig"

エクスポートしたファイルが、適正な kubectl 設定であることを確認します。

$ cat k8s-test.kubeconfig
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data:
    <Snip>
    server: https://35.226.99.100
  name: cluster
contexts:
- context:
    cluster: cluster
    namespace: default
    user: authInfo
  name: context
current-context: context
kind: Config
preferences: {}
users:
- name: authInfo
  user:
    auth-provider:
      config:
        cmd-args: config config-helper --format=json
        cmd-path: /snap/google-cloud-sdk/77/bin/gcloud
        expiry-key: '{.credential.token_expiry}'
        token-key: '{.credential.access_token}'
      name: gcp

上の内容を、別のマシン上の~/.kube/configファイルにマージします。

コンテキストの更新

既存のコンテキストにおいて項目を更新するにはdocker context updateを実行します。

以下の例は、既存のk8s-testコンテキストにおいて「Description」という項目を更新するものです。

$ docker context update k8s-test --description "Test Kubernetes cluster"
k8s-test
Successfully updated context "k8s-test"
engine, context, cli, kubernetes