目次


Docker Registry を Raspberry Pi 上のプルスルー型キャッシュとしてセットアップする

Docker と Pi を連動させて時間と帯域幅を節約する

Comments

低速のインターネット接続で、複数のユーザーが Docker イメージをダウンロードして作業しているとしたら、Docker Registry を Raspberry Pi 上のキャッシュとして使用することをお勧めします。こうすることによって、Docker を使用する際の時間と帯域幅の節約が可能になります。Raspberry Pi は持ち運びできて、値段が手頃で、しかも消費電力がごくわずかという、卓越したコンピューターです。このチュートリアルで説明するソリューションを作成すると、イメージをダウンロードするたびに Pi 上でキャッシュされて、以降のすべてのリクエストではローカル・キャッシュから同じイメージが配信されるようになります。

Docker はよく使われている DevOps ツールの 1 つです。Docker を使用すると、開発者とシステム管理者は場所を問わずにアプリケーションをビルド、配信、実行できます。つまり、開発者がローカル・マシン上で Docker イメージをビルドして、そのイメージをレジストリー配信し、クラウド・サーバー上でイメージを実行することができるのです。Docker イメージにとってのレジストリーとは、コードにとっての Git に相当します。

このチュートリアルで説明するセットアップは、時間の節約になるだけでなく、帯域幅の節約にもなります。Raspberry Pi は持ち運びできて、値段が手頃で、しかも消費電力がごくわずかという、卓越したコンピューターです。

レジストリーとしてよく使われている Docker Hub では、ユーザーが無料でイメージをホストできるようになっています。開発者のグループが同じ場所で Docker を使って作業している場合、インターネット接続が低速だったり帯域幅が限られていたりすると、開発者全員が Docker Hub からイメージをプルする際にパフォーマンスの問題が発生する可能性があります。そのような場合には、ローカル・ネットワーク上にプルスルー型キャッシュとして専用の Docker Registry をセットアップするという方法があります。こうすると、イメージをプルするたびに、そのイメージがキャッシュされて、以降のリクエストのたびにローカル・キャッシュからイメージが配信されることになります。これにより、貴重な帯域幅を節約できるだけでなく、時間も大幅に節約できます。例えば、Ubuntu ベースのイメージがプロキシーによってキャッシュされるとしたら、イメージを複数のマシンに何度ダウンロードするとしても、Docker Hub からそのイメージがフェッチされるのは 1 回だけです。

このチュートリアルでは、Docker Hub のプルスルー型キャッシュとして、Raspberry Pi を使用します。Raspberry Pi はクレジット・カードほどの大きさの小型コンピューターで、消費電力はほんのわずかであるにもかかわらず、完全な PC で実行できる処理のほとんどをこなすことができます。これから、Raspberry Pi をゼロからセットアップして、Golang を Raspberry Pi にインストールし、(Docker Registry は、クロスプラットフォーム言語の Golang で作成されているため) Go バイナリーをコンパイルする手順を説明します。すべてが順調に行けば、数時間でセットアップを完了できるはずです。まずは、前提条件を確認しましょう。

必要なハードウェアとソフトウェア

手順を開始する前に、以下のハードウェアが揃っていることを確認してください。

  • Raspberry バージョン 2 以降
  • SD カード (8GB 以上)
  • イーサネット・ポートが搭載されている Web ルーター
  • LAN ケーブル
  • Docker がインストールされているマシン

マシンには、以下のソフトウェアもインストールされている必要があります。

セットアップ

それでは、Raspberry Pi をセットアップするところから始めましょう。すでに稼働中の Raspberry Pi がある場合は、このステップを省略できます。Raspberry Pi には多数のディストリビューションがありますが、この例では Raspbian を使用します。Raspbian は、Raspberry Pi の Web サイト上で提供されている公式ディストリビューションです。

Raspbian をダウンロードする

新しいターミナル・ウィンドウを開き、wget を使用して Raspbian イメージをダウンロードします。wget は、ほとんどの Linux ディストリビューションにプリインストールされています。

$ mkdir -p ~/rpi-registry
$ cd ~/rpi-registry
$ wget https://downloads.raspberrypi.org/raspbian_lite/images/
raspbian_lite-2017-04-10/2017-04-10-raspbian-jessie-lite.zip

上記のコマンドによって、ディストリビューション・イメージがマシン上の「~/rpi-registry」ディレクトリー内にダウンロードされます。ダウンロードしたイメージの整合性を確認するために、SHA チェックサムをアップストリームの SHA と比較します。それには、以下のコマンドを実行します。

$ shasum 2017-04-10-raspbian-jessie-lite.zip
c24a4c7dd1a5957f303193fee712d0d2c0c6372d  
2017-04-10-raspbian-jessie-lite.zip

SHA チェックサムが一致しない場合は、イメージをもう一度ダウンロードする必要があります。低速のインターネット接続を使用しているとしたら、ダウンロードに torrent を使用してください。

SD カードを準備する

SD カードに Raspbian をインストールするには、Etcher というツールを使用します。このツールは https://etcher.io からダウンロードできます。Etcher は、SD カードと USB ドライブにイメージを書き込むアプリケーションです。Windows 用、Linux 用、Mac OS X 用の Etcher が用意されています。SD カードをラップトップまたはデスクトップに接続して、Etcher を開いてください。次に、ダウンロードした Raspbian イメージを選択し、イメージが SD カードを検出したことを確認してから、 「Flash! (フラッシュ)」 をクリックします (図 1 を参照)。SD カードへのイメージ書き込みが完了するまでには数分かかります。

図 1. イメージを SD カードに書き込む Etcher
イメージを SD カードに書き込む Etcher のスクリーン・キャプチャー
イメージを SD カードに書き込む Etcher のスクリーン・キャプチャー

ここではヘッドレス Pi をセットアップしています。つまり、Raspberry Pi にはキーボードやモニターを接続しないので、最初のブート時に SSH を有効にする必要があります。これが必要になる理由は、最新の Raspbian ビルドではデフォルトで SSH が無効にされているためです。SSH を有効にするには、初めて Raspberry Pi を起動する前に、SD カードのブート・パーティション内に「SSH」という名前を付けたファイルを作成します。ファイル名には拡張子を付けないでください。このファイルは空であっても、テキスト・ファイルであっても構いません。

ファイル・エクスプローラーまたはターミナルから SD カードを開くと、SSH が有効になります。Mac OS X 上でのマウント・パスは /Volumes/boot です。

$ cd /Volumes/boot
$ touch ssh
$ ls -la
...
-rwxrwxrwx  1 kn330  staff  4235224 Mar  2 16:52 kernel7.img
drwxrwxrwx  1 kn330  staff     8704 Apr 10 09:57 overlays
-rwxrwxrwx  1 kn330  staff        0 Jun 11 03:04 ssh
-rwxrwxrwx  1 kn330  staff  2848068 Apr  7 14:39 start.elf
...

これで、SD カードをブートできる状態になりました。SD カードを Raspberry Pi に挿入して、Raspberry Pi をホーム・ルーターに接続してください。

SSH ログイン

ログインするには Raspberry Pi の IP アドレスが必要です。IP アドレスは、ルーターの管理ページで確認できます。ほとんどのルーターの管理ページは 192.168.1.1 上で提供されていますが、これとは異なる場合もあるので、使用しているルーターの管理ページを手作業で調べてください (図 2 を参照)。あるいは、Nmap などのネットワーク・スキャニング・ツールを使用して IP アドレスを調べることもできます。

図 2. ルーターで確認できる Pi の IP アドレス
ルーターで確認できる Pi の IP アドレス
ルーターで確認できる Pi の IP アドレス

IP アドレスを確認した後は、ユーザー名として pi と入力し、パスワードとして raspberry と入力することで、セキュア・シェル (SSH) を使用できるようになります。pi と raspberry は、Raspbian オペレーティング・システムを使用する際のデフォルトのユーザー名およびパスワードとして Pi にあらかじめ設定されています。

$ ssh pi@192.168.1.2
pi@192.168.1.2's password:
The programs included with the Debian GNU/Linux system are free
software; the exact distribution terms for each program are described
in the individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
SSH is enabled and the default password for the 'pi' user has not
been changed.
This is a security risk - please login as the 'pi' user and type
'passwd' to set a new password.
pi@raspberrypi:~ $

これで Raspbian が稼働中になったので、次は Docker Registory をセットアップする作業に移ります。Pi に割り当てられる IP アドレスは変更される可能性があるため、静的 IP を割り当てることをお勧めします。

プロキシー: Docker イメージを配信する

Docker イメージを保管して配信するために使用できる Docker Registry は、ステートレスで、極めてスケーラブルなサーバー・サイド・アプリケーションです。Docker Hub には無料で使用できるホスト型レジストリーが用意されています。すべての Docker クライアントには、このホスト型レジストリーがデフォルトとして使用されるため、docker pull ubuntu を実行すると、Docker Hub からイメージがフェッチされます。イメージを常にインターネットからプルするのではなく、レジストリー・キャッシュを実行して、これらのイメージをローカルで保管することもできます。それには、自宅専用または組織専用のレジストリーを、Docker Registry を使用してセルフホストします。このオープンソース・アプリケーションは Golang で作成されていて、GitHub から入手できるようになっています。Docker Registry を Docker コンテナーとして実行することもできますが、ベアメタルの Raspberry Pi 上では、ソースから Docker Registry をビルドして、そのバイナリーを実行します。

プロキシーの仕組み

任意の Docker クライアントが初めてイメージをプルしようとすると、プロキシーが Docker Hub からイメージをフェッチすると同時に、ファイル・システム上にそのイメージのコピーを保管します。以降のリクエストでは、Docker Hub からではなく、ローカル・レジストリーからイメージが提供されます。さらに、このプロキシーには、アップストリームでのイメージの変更を検出して、クライアントに提供する前にイメージを更新できるだけの賢さも備わっています (図 3 を参照)。

図 3. あらゆる変更を検出する docker_proxy
あらゆる変更を検出する docker_proxy
あらゆる変更を検出する docker_proxy

手順

Golang を使用することで、複数のアーキテクチャー向けのクロスコンパイルが可能になります。つまり、ラップトップまたはデスクトップ上で以下の手順に従って Docker Registry のバイナリーをビルドして、それらのバイナリーを Raspberry Pi にコピーできるということです。単純にするために、ラップトップやデスクトップ上ではなく、Raspberry Pi 自体上でビルド・プロセスを実行する方法を説明します。

まずは Golang をインストールしましょう。

Golang をインストールする

Go をインストールするのに最も簡単な方法は、gvm (Golang Version Manager) を使用することです。gvm は、Ruby における rvm や、Python アプリケーションにおける virtualenv に相当します。

pi@raspberrypi:~ $ sudo apt-get update   pi@raspberrypi:~ $ sudo
 apt-get install -y curl git mercurial make  binutils bison gcc 
build-essential pi@raspberrypi:~ $ bash < <(curl -s -S -L
 https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/
gvm-installer) pi@raspberrypi:~ $ source /home/pi/.gvm/scripts/gvm

ログインするたびに gvm のソースを指定しなくても済むよう、/home/pi/.gvm/scripts/gvm を ~/.bashrc ファイルに追加することをお勧めします。

pi@raspberrypi:~ $ go install go1.4
pi@raspberrypi:~ $ go install go1.8
pi@raspberrypi:~ $ gvm use go1.8 [--default]
pi@raspberrypi:~ $ go -v
pi@raspberrypi:~ $ go version
 go version go1.4 linux/arm

注: Go 1.5 の C はコンパイルに使用されないので、Go 1.8 をインストールする前に Go 1.4 をダウンロードする必要があります。

レジストリーのバイナリーを作成する

Docker Registry リポジトリーには、バイナリーをビルドして bin ディレクトリー内に配置する Makefile が用意されています。Docker Registry は Docker Distribution リポジトリーの一部になっているので、このリポジトリーにアクセスして複製します。

pi@raspberrypi:~ $ git clone https://github.com/docker/distribution.git
pi@raspberrypi:~ $ cd distribution

次に、依存関係をインストールします。

pi@raspberrypi:~ $ go get ./...

バイナリーを作成します。

pi@raspberrypi:~ $ GOOS=linux GOARCH=arm make binaries

Linux オペレーティング・システム上の ARM アーキテクチャー用のビルドであることをコンパイラーが認識するように、GOOS および GOARCH 環境変数を設定します。make コマンドの実行が正常に完了すると、bin/ ディレクトリー内にバイナリーが生成されているはずです。

pi@raspberrypi:~/distribution $ ls bin/
digest  registry  registry-api-descriptor-template

バイナリー・パッケージをテストする

レジストリーを実行するための構成ファイルが必要です。 ~/registry-config.yml という名前のファイルを作成して、そこに以下の内容をコピーしてください。

version: 0.1
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000

レジストリーを実行するために必要なものがすべて揃ったので、早速、独自のプライベート・レジストリーを実行してください。

pi@raspberrypi:~ $ sudo mkdir -p /var/lib/registry
pi@raspberrypi:~ $ sudo chown $USER /var/lib/registry
pi@raspberrypi:~/distribution $ ~/distribution/bin/registry
 serve ~/registry-config.yml
WARN[0000] No HTTP secret provided - generated random secret. 
This may cause problems with uploads if multiple registries are 
behind a load-balancer. To provide a shared secret, fill in 
http.secret in the configuration file or set the 
REGISTRY_HTTP_SECRET environment variable.  go.version=go1.8
 instance.id=a80670e6-d840-44f3-aefa-9f6863fb6a6e
 version="v2.6.0+unknown"INFO[0000] redis not configured
 go.version=go1.8 instance.id=a80670e6-d840-44f3-aefa-
9f6863fb6a6e version="v2.6.0+unknown"
INFO[0000] Starting upload purge in 10m0s
go.version=go1.8 instance.id=a80670e6-d840-44f3-aefa-9f6863fb6a6e
 version="v2.6.0+unknown"
INFO[0000] using inmemory blob descriptor cache
go.version=go1.8 instance.id=a80670e6-d840-44f3-aefa-9f6863fb6a6e
 version="v2.6.0+unknown"
INFO[0000] Starting cached object TTL expiration scheduler...
go.version=go1.8 instance.id=a80670e6-d840-44f3-aefa-9f6863fb6a6e
 version="v2.6.0+unknown"
INFO[0001] Discovered token authentication URL:
https://auth.docker.io/token  go.version=go1.8 instance.id=
a80670e6-d840-44f3-aefa-9f6863fb6a6e
INFO[0001] Registry configured as a proxy cache to 
https://registry-1.docker.io  go.version=go1.8 instance.id=
a80670e6-d840-44f3-aefa-9f6863fb6a6e version="v2.6.0+unknown"
INFO[0001] listening on [::]:5000
go.version=go1.8 instance.id=a80670e6-d840-44f3-aefa-9f6863fb6a6e
version="v2.6.0+unknown"

これで、専用の Raspberry Pi 上で専用のレジストリーが稼働中になっています。警告メッセージがいくつか表示されることもありますが、今のところは無視して問題ありません。ラップトップからの接続も確認しましょう。

local-osx $  curl -I 192.168.1.2:5000/v2/
HTTP/1.1 200 OK
Content-Length: 2
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
Date: Sun, 11 Jun 2017 13:26:18 GMT

応答コード 200 が返されたら、接続に問題はないことになります。

プロキシーのセットアップ

レジストリーをテストして、正常に機能することを確認しました。けれども、ここで目的としている処理はまだ行われていません。したがって、最初にプルする際にイメージをキャッシュして、以降のリクエストにはローカルからイメージを提供するように、プロキシーをセットアップする必要があります。それには、構成ファイルに以下のプロキシー・セクションを追加することで対処できます。

version: 0.1
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
proxy:
 remoteurl: https://registry-1.docker.io

ここで、remoteurl は Docker Hub レジストリーの URL です。ポートは 5000 に設定されていますが、必要に応じて、他のどのポートにでも変更できます。前と同じコマンドを使用してレジストリーを実行します。

pi@raspberrypi:~/distribution $ ~/distribution/bin/registry serve
 ~/registry-config.yml &

このコマンドの末尾にある & に注目してください。これによって、プロセスはバックグラウンドで実行されます。次は、ラップトップ上でこのレジストリー・ミラーを使用するように Docker デーモンを構成します (図 4 を参照)。Mac 用の Docker を使用しているとしたら、「Preferences (設定)」 > 「Registry mirrors (レジストリー・ミラー)」にナビゲートして http://192.168.1.2:5000 を追加してから Docker を再起動すると、Docker デーモンがレジストリー・ミラーを使用するようになります。Mac 以外の OS 上で Docker を使用している場合は、該当するドキュメント (「関連トピック」を参照) に従って Docker デーモンの設定を更新してください。

図 4. Docker デーモンの構成
Docker デーモンの構成
Docker デーモンの構成

これで、ラップトップ上でイメージをプルするたびに、そのイメージが Raspberry Pi 上の /var/lib/registry ディレクトリーにキャッシュされるようになりました。このディレクトリー・パスに外部ドライブをマウントすることもできます。Mongo Docker イメージをプルして、動作を確認しましょう。

local-osx $ time docker pull mongo
Using default tag: latest
latest: Pulling from library/mongo
56c7afbcb0f1: Pull complete
...
e233325a655e: Pull complete
Digest:
sha256:c4bc4644b967a4b58022a79cf5c9afcd25ed08180c958a74df57b7753cfc8649
Status: Downloaded newer image for mongo:latest
docker pull mongo  0.15s user 0.18s system 0% cpu 2:22.28 total

local-osx $ docker rmi mongo

local-osx $ time docker pull mongo
Using default tag: latest
latest: Pulling from library/mongo
56c7afbcb0f1: Pull complete
...
e233325a655e: Pull complete
Digest: sha256:c4bc4644b967a4b58022a79cf5c9afcd25ed08180c958a74df57b7753cfc8649
Status: Downloaded newer image for mongo:latest
docker pull mongo  0.15s user 0.13s system 0% cpu 51.303 total

ご覧のように、最初のプル処理には 142 秒かかっていますが、2 回目のプル処理にかかった時間は 60 秒を下回っています。

まとめ

低速のインターネット接続を通じて複数のユーザーが Docker イメージをダウンロードしているとしたら、このチュートリアルで紹介したセットアップによって、時間と帯域幅の両方を節約できるようになります。Raspberry Pi は持ち運びできて、値段が手頃で、しかも消費電力がごくわずかという、卓越したコンピューターです。Raspberry Pi を Docker Hub のプルスルー型キャッシュとして使用することでもたらされるメリットは、このチュートリアルで理解していただけたように、イメージをダウンロードするたびにイメージが Pi 上でキャッシュされて、以降のリクエストのたびに、ローカル・キャッシュからイメージが配信されることです。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Cloud computing
ArticleID=1058679
ArticleTitle=Docker Registry を Raspberry Pi 上のプルスルー型キャッシュとしてセットアップする
publish-date=03082018