コンテナレジストリ(Lab)でDockerイメージを保存・配布する方法

# 概要

このチュートリアルでは、さくらのクラウド「[コンテナレジストリ](　https://manual.sakura.ad.jp/cloud/appliance/container-registry/#id5)」の概念を学んだ後、レジストリの作成やイメージのアップロードやダウンロード、ユーザ認証を設定する方法を学びます。

# 説明

## コンテナレジストリとは？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13002/cb1e2999-016f-b6d4-7d25-88d6e0aba550.png)


Docker イメージを保管・配布できるのは Docker Hub だけだと思っていませんか？ さくらのクラウド「[コンテナレジストリ](　https://manual.sakura.ad.jp/cloud/appliance/container-registry/#id5)」でもイメージの保管・配布だけでなく、複数の保存場所（レジストリ）を作ったり、必要に応じてユーザ認証も設定したりできます。Dockerイメージを保管・配布できる「コンテナレジストリ(Lab)」は [2020年12月から提供開始](https://cloud-news.sakura.ad.jp/2019/12/23/container-registry-lab-release/) しました。コンテナレジストリは国内のデータセンタ内にあり、通信 暗号化にも対応（Let's Encrypt）した、Docker Hub とプロトコルに互換性を持つレジストリ・サービスです。

※捕捉：  [Docker Hub](https://hub.docker.com/) は公開レジストリであり、docker コマンド操作時、pull や push が自動的に行われるデフォルトのレジストリです。

ちなみに、コンテナレジストリは「グローバルリソース」の扱いです。通常、サーバやネットワーク用スイッチなどのリソースは、「東京」や「石狩」といったゾーンに紐付く形で作成されますが、「グローバル」に相当する DNS や監視については、全ゾーン共通のリソースとして利用できます。

## コンテナレジストリのリソース作成手順

Docker イメージを置くには、まずはじめにコンテナレジストリの作成が必要です。さくらのクラウド コントロールパネルにログイン後、左メニューにある「 **Lab** 」→「 **コンテナレジストリ** 」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13002/534d79a0-968e-d02f-899f-ffda06ee93c7.png)


画面右上の 「 **追加** 」 をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13002/dc86720e-b56a-fc39-00ae-45dcbc94bec7.png)


次の追加画面では、必要項目を入力していきます。

今回は「初めてのレジストリ」と言う名前で、コンテナレジストリ名には好きな任意の名称（他人と重複できません）、公開設定は「非公開」にしましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13002/969d6841-641f-0e5e-8323-d7cf8379f071.png)


* 「名前」…コントロールパネル上で表示する名前です
* 「コンテナレジストリ名」… レジストリへの接続は **「入力した名前」.sakuracr.jp ** で行います
* 「公開設定」…レジストリに **認証を設けるかどうか** を設定します
  * 「Push & Pull」…誰でもイメージを送受信できます（認証なし）
  * 「Pull のみ」…イメージをアップロード（push）時に認証を必要とします（Docker Hubと同じ）
  * 「非公開」…イメージのアップロード（push）とダウンロード（pull）の両方に認証をかけます

なお、もしドメイン名をお持ちの場合は「独自ドメイン」に FQDN を入力すると、その名前でもアクセスが可能になります。その際、DNS サーバでは CNAME 設定をコンテナレジストリ名にする作業が必要です。詳しくは [ドキュメント](https://manual.sakura.ad.jp/cloud/appliance/container-registry/#id5)をご覧ください。

入力内容の確認後、画面右下の「 **作成** 」をクリックします。

次の「操作確認」ダイアログでは、内容を確認の後、「 **同意して作成** 」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13002/7cfd5ea2-dd8d-12cb-dc49-b43b7a5d40e5.png)


ダイアログ画面で「成功」にステータスが切り替わったら、「 **閉じる** 」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13002/b530fa92-ce7d-b842-2c37-42685cc96ad2.png)


それから再び、左メニューの「コンテナレジストリ」をクリックすると、先ほど作成したレジストリが画面上に表示されます。

## レジストリのユーザ作成

レジストリの「公開設定」を「Push&&Pull」にした場合は、このユーザ作成の手順は不要です。このチュートリアルでは「非公開」を選択しましたので、利用する前にレジストリに接続可能なユーザを作成します。

まず、レジストリ一覧から、対象のレジストリ名をダブルクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13002/747ee74c-54a2-ddb2-19c0-8ba431982e50.png)


次の画面ではレジストリの情報が表示されています。ここでは「 **ユーザ** 」のタブをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13002/e7a7e8b5-38c2-bc84-28c6-e659f079ddd3.png)



それから、右下にある「 **追加** 」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13002/1abfe087-a7b4-16da-1a8e-62ac1bc0f9fb.png)


その次の「ユーザ」ダイアログでは、任意の「 **ユーザ名** 」（コンテナレジストリへのログイン時に必要です）、「 **パスワード** 」を入力し、ユーザ権限設定を「All」（push や pull 以外にも削除等を含む全ての権限）のまま、「 **作成** 」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13002/bbbb2c77-51ac-a966-35aa-c58b620fecad.png)


正常に処理が完了すると、画面上にユーザが作成されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13002/a4ad305b-4ddf-3829-8047-067315e91406.png)


これでコンテナレジストリ側の準備は調いました。

## 自分の Docker イメージをアップロードする方法

ポイント：アップロード時に気を付けるのは、イメージ名を「 **＜コンテナレジストリ名＞.sakuracr.jp/＜イメージ名＞** 」の形式にする必要があること。

### まずはイメージを準備

ここでは、簡単なサンプルイメージを作成します。

何らかのディレクトリを作成し、移動します。

```
$ mkdir mynginx
$ cd mynginx
```

それから、次の内容の「Dockerfile」という名称のファイルを作成します。

```Dockerfile
FROM nginx:alpine
RUN echo '<h1>Hello world with Docker!</h1>' > /usr/share/nginx/html/index.html
```

そして、この Dockerfile をもとに、イメージを構築（ビルド）します。実行するコマンドは `docker build -t ＜作成したレジストリ名＞.sakuracr.jp/hello-nginx:latest .` です。

```
$ docker build -t registry-example.sakuracr.jp/hello-nginx:latest .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM nginx:alpine
alpine: Pulling from library/nginx
4167d3e14976: Pull complete
bb292c78f105: Pull complete
Digest: sha256:abe5ce652eb78d9c793df34453fddde12bb4d93d9fbf2c363d0992726e4d2cad
Status: Downloaded newer image for nginx:alpine
 ---> 377c0837328f
Step 2/2 : RUN echo '<h1>Hello world with Docker!</h1>' > /usr/share/nginx/html/index.html
 ---> Running in 1951f21abaa7
Removing intermediate container 1951f21abaa7
 ---> 5636fb0f6dad
Successfully built 5636fb0f6dad
Successfully tagged registry-example.sakuracr.jp/hello-nginx:latest
```

このように表示されていれば問題ありません。ここでローカルにあるイメージ一覧を表示する「docker images」を実行します。

```
$ docker images
REPOSITORY                                 TAG                 IMAGE ID            CREATED             SIZE
registry-example.sakuracr.jp/hello-nginx   latest              5636fb0f6dad        35 seconds ago      19.7MB
nginx                                      alpine              377c0837328f        38 hours ago        19.7MB
```

このように作成されていれば問題ありません。

今回はチュートリアルのため、ビルド時のタイミングでイメージ名にレジストリのホスト名も含めました。ビルド時でなくとも、イメージの作成後に、「docker tag」コマンドでイメージ名にホスト名を含めても構いません。

### レジストリにログイン

イメージを送信する前に「docker login <レジストリ名>」コマンドでレジストリにログインします。

```
$ docker login registry-example.sakuracr.jp
Username: example
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
```

このような表示になれば、正常にログインできました。

エラー「Error response from daemon: Get https://registry-example.sakuracr.jp/v2/: unauthorized: authentication required」が表示された場合は、認証するユーザ名かパスワードが違います。正しいかどうかご確認ください。

### イメージのアップロード

イメージを送信するには、認証後、「docker push」コマンドでイメージを送信します。送信時には、イメージにレジストリ名が付いている必要があるのを、忘れないでください。

```
$ docker push registry-example.sakuracr.jp/hello-nginx
The push refers to repository [registry-example.sakuracr.jp/hello-nginx]
f3dd4fec699b: Pushed
6f23cf4d16de: Pushed
531743b7098c: Pushed
latest: digest: sha256:b0e20778aef9dde51c6f0101b3ea50908d6165c66df51c5422b5e75a9ff09262 size: 946
```

特にエラーが出なければ送信完了です。

### 動作確認

イメージをアップロードしたので、ローカルのイメージは削除できます。「docker rmi」コマンドでイメージを削除しましょう。

```
# docker rmi registry-example.sakuracr.jp/hello-nginx
Untagged: registry-example.sakuracr.jp/hello-nginx:latest
Untagged: registry-example.sakuracr.jp/hello-nginx@sha256:b0e20778aef9dde51c6f0101b3ea50908d6165c66df51c5422b5e75a9ff09262
Deleted: sha256:5636fb0f6dadb2f17a413e092f1625ddbbe48237ef7cac39fe39ad08275216ad
Deleted: sha256:80240c8ed42d58137142581c30f34fd594e9a4dbf23c54d98787398ebcbf9431
```

「docker images」コマンドを実行すると、イメージ作成の元になった「nginx:alpine」のみが残ったままです。


```
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               alpine              377c0837328f        38 hours ago        19.7MB
```

この状態で、レジストリからイメージをダウンロードします。今度は「docker push」の逆で、「docker pull」を使います。

```
$ docker pull registry-example.sakuracr.jp/hello-nginx
Using default tag: latest
latest: Pulling from hello-nginx
4167d3e14976: Already exists
bb292c78f105: Already exists
619bae5a1971: Pull complete
Digest: sha256:b0e20778aef9dde51c6f0101b3ea50908d6165c66df51c5422b5e75a9ff09262
Status: Downloaded newer image for registry-example.sakuracr.jp/hello-nginx:latest
registry-example.sakuracr.jp/hello-nginx:latest
```

そして「docker images」を実行しましょう。ダウンロードされていれば、イメージ名が表示されているはずです。

あとは、このイメージを使ってコンテナを実行しましょう。

```
$ docker run --rm -p 8080:80 registry-example.sakuracr.jp/hello-nginx
```

コマンド実行後、 Docker を実行している <ホストのIP> を確認し、ブラウザで `http:/IPアドレス:8080/` を開きます。先ほどビルドした、改変済みのウェブサイトのトップページ `Hello world with Docker!` が表示されていれば大丈夫です！

実行中の Nginx コンテナは「Ctrl+C」で中断・停止できます。

### レジストリからログアウト

最後に [docker logout <レジストリ名>.sakuracr.jp]を実行してログアウト（正確には、ローカルに保存している認証情報の削除）します。

```
$ docker logout registry-example.sakuracr.jp
Removing login credentials for registry-example.sakuracr.jp
```

そして、ログアウト後は権限がありませんので、再度イメージを取得しようとしても次の様にエラーが出ます。

```
$ docker pull registry-example.sakuracr.jp/hello-nginx
Using default tag: latest
Error response from daemon: Get https://registry-example.sakuracr.jp/v2/hello-nginx/manifests/latest: unauthorized: authentication required
```

# まとめ＆振り返り

さくらのクラウドで Docker イメージを共有できる「コンテナレジストリ」を操作するための基本的な概念と、操作方法を学びました。また、コマンドを実行しながら、レジストリへのログインや、自分でカスタマイズした Nginx イメージ共有を行いました。Docker Hub と異なり、複数のレジストリの作成や、こまかなユーザ権限の設定もできますので、ぜひ色々とお試しくださいね。


# 参考情報

- コンテナレジストリ(Lab) | さくらのクラウド ドキュメント
  - https://manual.sakura.ad.jp/cloud/appliance/container-registry/#id5