本連載では、Docker に興味はありつつも、まだ触ったことのない方向けに、実際に触って Docker について理解していただくための記事を提供します。第2回では、Dockerfileからイメージをビルドする方法を紹介しました。ローカルでビルドしたイメージは、Docker Engine にキャッシュされているだけで、他の人には利用できません。イメージを他の人に使ってもらうには、利用者がアクセスできる場所にイメージを公開する必要があります。Docker 社や AWS を始めとする各種クラウドベンダーは、Docker イメージを管理・共有する仕組みとして、「レジストリ」というサービスを提供しています。今回は、Docker イメージのレジストリとして、Docker Hub および AWS ECR(EC2 Container Registry)の概要、簡単なイメージ登録・取得の方法、およびチーム内でイメージを管理する際の考慮すべき事項について紹介します。
レジストリでイメージを共有する
最初に、チームでのイメージ管理の仕組みについて概要を理解していただくため、ベンダー非依存なレベルでのリジストリの概要について紹介します。個別のサービスに依存した部分については、サービスごとの節で紹介します。
レジストリは、チームでイメージを管理・共有するため、主に2つの役割を提供しています。
- イメージの登録および共有
- イメージの保管場所としてイメージを登録できる。
- 他の利用者にイメージを公開できる。
- イメージへのアクセス制限(認証・認可)
- 特定の人にだけイメージへの書き込みや読み取りを許可する。
以下は、レジストリサービスの概念図です。
- 「レジストリ」はイメージを登録するサービス全体を指します。
- レジストリ内には、公開したいイメージ(Nginx や Node.js など)のカテゴリごとに「リポジトリ」があり、実際のイメージはリポジトリに登録されます。
- リポジトリ内にはイメージを複数登録でき、各イメージはタグで区別されます。バージョン番号ごとにイメージを区別したい場合などは、タグにバージョン番号を指定します。
例えば、Docker 公式の Node. js イメージの場合、7.7.4 や 7.7.4-alpine というように Node.js のバージョン番号や Linux ディストリビューションなど、イメージの内容をタグで表現しています。
- (注)タグが同じイメージは上書きされてしまうため、リポジトリにイメージを push する際は注意が必要です。
- 最初にレジストリにアクセスする際は認証が必要になります。また、push や pull などリポジトリに対する操作について、ユーザごとにアクセス権を設定できます。よって、イメージを管理する人にはリポジトリへの push の権限を与え、イメージを利用する人には pull の権限を与えるというような運用が可能です。
Docker Hub - Docker 社公式のレジストリ
次に個別のレジストリについて説明します。 最初に Docker 社がクラウドサービスとして提供している Docker Hub を紹介します。
Docker Hubとは
Docker Hub は、Docker 社が提供しているイメージ管理用クラウドサービスです。特徴は以下の通りです。
- 完全マネージド型
- Docker 社で管理しているクラウドサービスのため、自分でサーバを管理する必要はない。
- Web UI
- イメージや Docker Hub のアカウント管理をブラウザ上で行える。
- メタデータストア
- ユーザ間のコミュニケーション支援のためリポジトリにコメントをつけたり、スター(Facebook の「いいね」に相当)をつけたりすることができる。
- 認証・認可
- リポジトリにアクセスする他ユーザに対してイメージの読み取り・書き込み・管理などのアクセス制限をかけることができる。
- チームでのリポジトリ共有・管理
- チームでリポジトリを共有し、共同で管理できる。
- Webhook
- CI / CD 環境と連携するための Webhook を提供する。
Docker Hub へイメージを push / pull してみよう
ここからは実際に公開リポジトリを作成し、そのリポジトリに対してイメージをpushします。 第2回でビルドしたイメージを利用しますので、第2回のチュートリアルを実施していない方は、第2回の方を先に読んでからこれ以降の記事をお読みください。
リポジトリを作成する
リポジトリを作成するには、Docker Hub のアカウントが必要になります。Docker Hub にアクセスして、事前にアカウントを作成してください。
次に Docker Hub にログイン後の画面で「Create Repository」をクリックして、リポジトリ作成画面を表示してください。リポジトリ名はイメージと同じ「myfirstapp」を指定してください。Visibility は public (公開)のままで結構です。
レジストリの認証を行う
リポジトリにイメージを push する前にレジストリの認証を行う必要があります。username と password の入力を求められますので、Docker Hub に登録したものを入力してください。Login Succeeded と表示されれば、ログイン成功です。
$ docker login Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: yohei1126 Password: Login Succeeded
リポジトリにイメージを push する
リポジトリに push するイメージ名は「リポジトリ名/イメージ名」とする必要があります。Docker Hub の場合、リポジトリ名はアカウント名(筆者の場合 yohei1126)です。
第2回のローカルでビルドしたイメージにはリポジトリ名が明示されていないため、以下に示す docker tag コマンドで Docker Hub に push できる別名を設定する必要があります。なお、第1引数に別名を設定したいイメージID、第2引数に別名を指定します。それぞれご自身の環境に合わせて変更してください。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE myfirstapp latest 472a32c8188b 26 minutes ago 65.6 MB $ docker tag 472a32c8188b yohei1126/myfirstapp
docker images イメージ一覧を表示すると、docker tag の結果、「yohei1126/myfirstapp」が追加されたことが分かります。ただし、「myfirstapp」と「yohei1126/myfirstapp」の「IMAGE ID」(イメージの識別子)が同じですので、両者は同一のイメージに対する別名であることがわかります。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE myfirstapp latest 472a32c8188b 26 minutes ago 65.6 MB yohei1126/myfirstapp latest 472a32c8188b 26 minutes ago 65.6 MB
次に docker push コマンドでリポジトリに対して、イメージを push します。
$ docker push yohei1126/myfirstapp The push refers to a repository [docker.io/yohei1126/myfirstapp] 17c42ed7fd27: Pushed 213ceaccd73e: Pushed ac71ddba259e: Pushed f8a68ba3c32d: Pushed 509e95f0d599: Pushed 3369321ad418: Pushed 23b9c7b43573: Pushed latest: digest: sha256:7844dcb21756932f0cc93399519159f02f6c7b68f86af516d30c50b18b85d2ea size: 1783
再び、ブラウザで Docker Hub のダッシュボードを開き、さきほど作成したリポジトリ myfirstapp の Tags(タグ一覧)を見ると、タグ latest としてイメージが push されたことがわかります。これは先程の push 時にイメージの tag を省略していたため、最新イメージを指すデフォルトの tag である latest が指定されたためです。
イメージのバージョン管理などの目的にタグを明示的に指定したい場合は、以下のようにイメージ名として「リポジトリ名/イメージ名:タグ」とタグを明示的につけてから、push してください。
$ docker tag 472a32c8188b yohei1126/myfirstapp:0.0.1 $ docker push yohei1126/myfirstapp:0.0.1
プライベートリポジトリをチームで共有するには?
ここまでの内容は、個人の公開リポジトリにイメージを push する方法を紹介しました。公開リポジトリですので、以下のコマンドを打てば誰でもイメージを pull できてしまいます。
$ docker pull yohei1126/myfirstapp
しかし、個人のプロジェクトであれば、個人アカウントに公開リポジトリを用意しても良いでしょうが、実際の開発では、チーム用のプライベートリポジトリを用意し、チームメンバのみアクセスできるようにしたいでしょう。
まず、Docker Hub ではプライベートリポジトリを作成できます。ただし、1 個まで無料、それ以上は有料です。料金は Docker Hub のダッシュボードで Pricing のページを参照ください。
次に、チーム用のリポジトリを作るため、Docker Hub には Organization と Team という機能があります。Organization はチームメンバが所属する組織を意味し、Team はその組織内の特定の役割をもったチームを意味します。
具体例として、トラブルを防ぐため、イメージの管理者だけイメージを push できるようにし、その他のメンバは pull だけできるようにしたい場合は、以下の通りに Organization と Team を用意します。
- Organization としてチームメンバ全員を登録する。これでその Organization 配下に用意したプライベートリポジトリをメンバ全員が閲覧できるようになる。
- イメージ管理者の Team を用意し、リポジトリへの書き込み権限をつけた上で、その Team へイメージ管理者を登録する。これでイメージ管理者はリポジトリにイメージを push できる。
- イメージ利用者の Team を用意し、リポジトリの読み取り権限をつけた上で、その Team へイメージ利用者を登録する。これでイメージ利用者はリポジトリからイメージを pull できる。
詳細については Docker のドキュメントを参照ください。
AWS ECR を利用したイメージの管理
次に AWS で提供されているイメージのリポジトリとして AWS ECR(EC2 Container Registry)を紹介します。
ECRとは
ECR は、AWS 社が提供しているイメージ管理用クラウドサービスです。他の AWS のサービスと容易に連携できるため、AWS を活用されている方には非常に使いやすいサービスです。
具体的には以下の機能を持っています。
- 完全マネージド型
- AWS 社でマネージド・サービスとして管理されているクラウドサービスのため、自分でサーバを管理する必要はない。
- Web UI
- ブラウザを使い、AWS の管理コンソール上でイメージの管理を行える。
- 他の AWS サービスと簡単に連携できる。
- 連携の例
- AWS の認証基盤である AWS IAM(Identity and Access Management) で認証・認可を行う。
- AWS のコンテナ・クラスタ管理サービスである AWS ECS(EC2 Container Service) にコンテナをデプロイする。
- AWS CodeBuild 、AWS CodeDeploy、AWS CodePipeline などと組み合わせて、CI / CD 環境を構築する。
- 連携の例
- 認証・認可
- IAM を使い、イメージに対する認証・認可を行う。
- チームでのリポジトリ管理
- チームで共有のリポジトリを作成できる(IAM の機能を使い、DockerHub の Organization および Team 相当の機能を実現できる)。
なお、ECR に利用料金はありませんが、ポジトリに保存するデータとインターネットに転送するデータの量に対して課金されます。詳しくは料金表をご確認ください。
ECR へイメージを push / pull してみよう
ECR を利用するには以下を事前に準備する必要があります。
- AWS のアカウントを用意する。
- 詳細は AWS のドキュメント を参照ください。
- IAM ユーザを作成する。
- リポジトリへのアクセスは、IAM を使って認証・認可を行うため、IAM ユーザが必要です。AWS のドキュメント を参考に IAM ユーザを作成してくだい。
- AWS CLI(コマンドラインインタフェース)のインストール
- リポジトリの操作を CLI 上で行うため、AWS のドキュメント を参考に、CLI を事前にインストールしてください。
- aws configure コマンドでキーおよびリージョンの設定も実施してください。
(注)これ以降は AdministratorAccess のポリシーがついた IAM ユーザで作業することを想定しています。
レジストリの認証を行う
イメージを ECR に push するには、事前に CLI でレジストリに対する認証を行っておく必要があります。認証は Docker Hub と同様に docker login コマンドで行います。
(注) ECR へログインする docker login コマンドには、AWS 固有の認証情報を付加する必要があり、AWS CLI コマンドで自動生成する点に注意してください。
以下のコマンドを実行し、docker login コマンドを取得してください。「–region」の後は、リポジトリを作成するリージョンを指定してください。ログインに成功すれば、docker login コマンドが表示されます。 (注)以下は、認証情報を省略しています。実際には長い文字列が表示されます。
$ aws ecr get-login --region us-west-2 docker login -u AWS -p xxx -e none https://xxx.dkr.ecr.us-west-2.amazonaws.com
次に表示された docker login コマンドを実行してください。成功すれば「Login Succeeded」と表示されます。
$ docker login -u AWS -p xxx -e none https://xxx.dkr.ecr.us-west-2.amazonaws.com Flag --email has been deprecated, will be removed in 1.14. Login Succeeded
なお、AWS CLI で取得した docker login コマンドには有効期限があります。一定時間が立てば、レジストリにアクセスできなくなりますので、その際はレジストリの認証からやり直してください。
リポジトリを作成する
イメージを push する先として、リポジトリを用意します。
ブラウザでリポジトリを作成する場合は、以下の手順を実施してください。
- https://console.aws.amazon.com/ecs/ にアクセスし、AWS ECS (EC2 Container Service) の管理コンソールを開いてください。(注)ECR は ECS に統合されており、イメージの管理も ECS の管理コンソール上で行います。
- 「リポジトリの設定画面」でリポジトリ名として「myfirstapp」と入力し、「次のステップ」を押してください。
- リポジトリの URI が表示されますので、後の作業のため控えておいてください。URIの書式は、「アカウント番号.dkr.ecr.リージョン名.amazonaws.com/リポジトリ名」です。
なお、CLI の場合、以下のコマンドで作成できます。
$ aws ecr create-repository --repository-name myfirstapp { "repository": { "registryId": "xxx", "repositoryName": "myfirstapp", "repositoryArn": "arn:aws:ecr:us-west-2:xxx:repository/myfirstapp2", "createdAt": 1490510283.0, "repositoryUri": "xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp2" } }
リポジトリにイメージを push する
リポジトリにイメージを push するには、docker tag コマンドでリポジトリ名を明示したイメージ名の別名を用意する必要があります。別名には管理コンソールまたは CLI の応答に表示されたリポジトリの URI を指定してください。
$ docker tag myfirstapp xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp
docker push すると無事にイメージが push されました。
$ docker push xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp The push refers to a repository [xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp] 17c42ed7fd27: Pushed 213ceaccd73e: Pushed ac71ddba259e: Pushed f8a68ba3c32d: Pushed 509e95f0d599: Pushed 3369321ad418: Pushed 23b9c7b43573: Pushed latest: digest: sha256:7844dcb21756932f0cc93399519159f02f6c7b68f86af516d30c50b18b85d2ea size: 1783
イメージを pull するときもリポジトリを明示してイメージ名を指定します。
$ docker pull xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp
プライベートリポジトリをチームで共有するには?
DockerHub と同様にチームメンバの IAM ユーザのグループに対して、IAM ポリシーを設定することで、イメージ管理者全員に push を許可し、イメージ利用者全員に pull を許可することは可能です。
なお、ECR の場合、デフォルトでリポジトリはプライベートですので、許可した相手に対して特定の操作を許可していく方法を取ります。
具体的な権限設定の方法としては、以下の2通りがあります。どちらも最終的には、IAM ポリシーが IAM ユーザに適用されるという点で同じですが、後者の管理コンソールを使う方法が初心者にも分かりやすくおすすめです。
- (ECR 以外のサービスと共通)直接 IAM ポリシーを作成し、ユーザにアタッチする。
- リポジトリに対して適切なアクセス権限を設定した IAM ポリシーを作成し、許可したい IAM ユーザやユーザグループにアタッチする。
- 詳細は AWS のドキュメントを参照。
- メリット
- CLI で実施できるため、自動設定したい場合に有効。
- デメリット
- IAM 自体が複雑なため、IAM ポリシーを書き間違って、適切な権限を設定できないリスクがある。実施の際は検証が必要。
- (ECR 限定)ECRの管理コンソールで設定する
- 実施方法
- ECR の管理コンソールでリポジトリの「アクセス権限」のページを開き、リポジトリの管理ポリシーを作成する。
- 詳細は AWS のドキュメントを参照。
- メリット
- 管理コンソール上の GUI で操作できる。CUI に慣れていない人には分かりやすい。
- ユーザを選んで、「pull だけ」・「pushとpull」・「全ての3つ」から許可したい操作を選ぶだけなので、誰に何を許可しているのか分かりやすい。
- デメリット
- GUI ベースなので、自動化しづらい。
- 実施方法
おわりに
今回は、ビルドしたイメージを共有する方法として、レジストリサービスを紹介しました。また、具体的なレジストリサービスとして、Docker Hub と Amazon ECR を題材に、リポジトリの管理やイメージを push する方法について紹介しました。今回、チーム内で共有する際のアクセス権限の管理方法については、概要のみ説明しましたが、実際のプロジェクトで適用する際にはトラブルを防止するため、適切なリポジトリのアクセス権限ポリシーを策定することが重要になります。本文中で紹介した Docker や AWS のドキュメントを参考に事前に検証した上で導入することをおすすめします。