周回遅れのDocker 4: Docker Hub によるイメージの配布と利用


Docker イメージの配布用として利用することができる「Docker Hub」を使って、コンテナ化した任意のアプリケーションを Docker Hub に登録し、そのイメージを使って動かしてみる。

Dockerコンテナとして稼働させるアプリケーションには、自前の Web アプリケーションである、[Twitch](http://www.twitch.tv/)をザッピング視聴できる [tswitch](https://github.com/kumatch/tswitch) を選択。


## コンテナの構築とローカルテスト

コンテナへアプリケーションを同梱するための Dockefile は以下のようなものを用意した。
Node アプリケーションなのでベースのイメージは [node](https://registry.hub.docker.com/_/node/) を選択。以後、基本的にやっていることは以下の４点。
 
* アプリケーションディレクトリを作成
* Github からアプリケーションを git clone してくる
* アプリケーションに必要な Node modules をインストール
* プロセス起動
* アプリケーションの待ち受けポートである TCP 3000 を `EXPOSE` でコンテナ待ち受けに

```Dockerfile
FROM node:0.12
MAINTAINER kumatch

RUN mkdir -p /data/

RUN git clone --depth 1 https://github.com/kumatch/tswitch.git /data/tswitch
WORKDIR /data/tswitch

RUN npm install --production
CMD npm start

EXPOSE 3000
```

ここで `EXPOSE` による待ち受けポート宣言について[ドキュメント](https://docs.docker.com/reference/builder/#expose)によると、 **`docker run` 時の `-P` オプションによるコンテナ待ち受けポートの公開を行う場合**、あるいは **`--link` オプションによるコンテナ間連携を行う場合** に必要なものであって、コンテナを動かす際 `-p` オプションでポートマッピングを指定するのであれば必須ではない模様。ただコンテナ自体をどう動かすかは利用者によるので、3000 で待ち受けるサーバであるならば明示的に指定してあげておくというのが現実と思われる。

上記 Dokerfile が妥当かどうか一度手元でビルドをしてみて、ちゃんと利用できることをチェックする。

```bash
$ docker build -t tswitch .
$ docker run --name tswitch -p 80:3000 -d tswitch
```

Docker ホストに HTTP アクセス。ちゃんとサービスが動くことが確認できた。

この内容を GitHub リポジトリへ登録。Docker Hub からは、この GitHub リポジトリを指定してイメージ登録を行うことになる。

今回作成した GitHub リポジトリは, https://github.com/kumatch/docker-tswitch に。


## Docker Hub へのイメージ登録。

### Docker Hub ユーザ登録

まずは Docker Hub にユーザ登録。
メールによるユーザ確認等、一通りのことを済ませる。

https://hub.docker.com/account/signup/


### Docker リポジトリ作成

Docker Hub で配布するイメージは、先ほど作成した GitHub リポジトリから情報を取ってきてもらって、Docker Hub 上でビルドしてもらう。

「Add Repository」=>「Automated Build」を選択。ソース元は GitHub, BitBucket から選択可能。GitHub を選ぶ。

GitHub 認証後、自分の Git リポジトリ一覧から先ほど作成した docker-tswitch を選択。このあと、GitHub リポジトリの名称に対する、Docker Hub リポジトリ側での名称を設定することができる。もちろんそのままでも良いが、GitHub 側では「docker-」というプレフィックスをつけたのに対して Docker Hub 側では冗長なので、プレフィックスを削除して「tswitch」 とした。

以上で作成が完了。あとは Docker Hub 上でのイメージビルドが終わるのを待つ。
以下のように Status が Finished になれば完了。


![スクリーンショット 2015-07-06 23.43.52.png](https://qiita-image-store.s3.amazonaws.com/0/18511/e90bf6f6-c551-3881-f714-d1d89cc4617d.png "スクリーンショット 2015-07-06 23.43.52.png")

以上で、今回登録して出来上がった Docker Hub リポジトリは https://registry.hub.docker.com/u/kumatch/tswitch/ に。


### Docker Hub イメージを使ってコンテナ起動

登録して利用できるようになった Docker Hub イメージを指定して、コンテナを起動してみる。

念のため、先ほどのローカルテストのイメージを削除しておくのと、構築した Dockerfile がない別ディレクトリへの移動をやって試した。

```bash
$ docker rmi tswitch
$ cd ~/

$ docker run --name tswitch -p 80:3000 -d kumatch/tswitch

Unable to find image 'kumatch/tswitch:latest' locally
latest: Pulling from kumatch/tswitch
fcf9fd1f0d1a: Pull complete
190ad010f550: Pull complete
4aab3d79c5a6: Pull complete
250775bf409f: Pull complete
42ed5dc9e8f5: Pull complete
6474603a448c: Pull complete
204408860b22: Pull complete
444ff6f3c9ae: Already exists
64e5325c0d9d: Already exists
bf84c1d84a8f: Already exists
87de57de6955: Already exists
6a974bea7c0d: Already exists
4b708e6c0f6c: Already exists
313c5b9e573c: Already exists
89027f845e09: Already exists
43361a3a20a4: Already exists
febb014eb418: Already exists
20a32f7a591c: Already exists
Digest: sha256:378b6b3f26b5d448c0873945f0fbc9ac4b6fc60d5365d7f15f7eb7df22b4a00b
Status: Downloaded newer image for kumatch/tswitch:latest
90edb1b8fddaf7f00b9f162e544206e8bcb4f39573edf5a739956c610c650ae1
```

Docker Hub からの自前イメージのダウンロードログが流れて、コンテナが起動。
改めて Docker ホストに HTTP アクセスして、先ほどのローカルテストと同様サービスが動くことを確認した。

## 備考: アップロードによるイメージ登録

Docker Hub へのイメージ登録は、ローカルでビルドしたイメージをアップロードして行うこともできる。

最初に `docker login` コマンドを使って, Docker からの Docker Hub ユーザ認証を行う。
この時 Docker ホストも起動している必要がある。

```bash
$ docker login
```

Dockerfile があるディレクトリで `docker push` コマンドを実行して任意の名称で登録する。

```bash
$ docker push kumatch/tswitch
```

（イメージ内容にもよると思うけど）比較的大きなファイルサイズをアップロードすることになるので時間がかかる。普通は GitHub 連携による Auto Build が楽だし良さそう。

ただ、GitHub 側の WebHook トリガがおかしい、あるいは Docker Hub 側の Automated Build のキューが溜まりすぎてなかなかイメージビルドが始めらないけどもイメージ配布はすぐに行いたいとき、はたまた プライベートな Docker イメージ配布を行いたくてそもそも公開 Git リポジトリを使って運用することができない、といったシーンでは使うことが出てくるとは思う。