社内サーバにDocker Registryを作ってイメージをやり取りしてみた
こんにちは、Dockerおじさんです。前回こんなことをやりました。
mao-instantlife.hatenablog.com
今回はこれの続きで、Docker Registryを使ってイメージのやり取りをやってみたのでそのまとめです。
やりたいこと
すごく雑な絵ですが、こんな感じです。
社内ツールとして使うアプリケーションもあり、展開する自社サービスもあります。どちらもDockerでインフラ構成を一元的に扱いたいのですが、扱ってるデータの関係上社外にアクセスしてはならないサーバもあるわけです。これらのサーバとイメージをやり取りするためのDocker Registryを社内に作ってしまえば良い、という訳ですね。
ちなみに、DockerのコンテナイメージをRegistryに対してpushやらpullやらでやり取りする場合はsshでアクセスします(当然ながら)。社内で作ったサーバには当然認証局に登録された証明書がないので、この辺りを解決しなければなりませんが、Docker Registryは二つの方法を提示してくれています。
- プレインHTTPを使う
- 自己認証の証明書を使う
どちらもクライアントとなるDockerホストの側に設定が必要です。さすがに前者はまずいと思ったので、後者で進めていきます。
Docker Registryの構築
Cent OS 7.1でお試し用のサーバを作ってもらい、Docker Registryを構築してみます。このCent OS上にはDocker Machineをインストールして、genericドライバでサーバローカルにDocker環境を構築しています。なお、このときサーバの認証を鍵認証だけにしてssh鍵のパスフレーズを無しにしないとdockerホストを作れませんでした *1 。この辺はあまり詳しくないので、社内のインフラ詳しい人と相談しながら実運用までに良いポイントを探っていこうかと。
まずはローカルで
ぶっちゃけ以下のURLの通りやれば良いです。
自己認証の証明書を使ってDocker Registryを立ち上げる
こっちについても、上記URLの「Running a domain registry」セクションと以下のURLを参考にすれば問題ありません。
証明書を作るときに後ではまったのは、Common Nameにホスト名を設定していなくて認証対象がローカルで解決できなかったことですが、完全に私の不注意レベルの話なので、ほとんどの人は大丈夫ではないかと思います。
イメージの配置場所など運用面で考慮しなければならないことは多々ありますが、Registryの立ち上げにはあまり困ることはなさそうです。
クライアント側の設定など
クライアントとなる別のマシンから先ほど構築したDocker Registryに対してイメージのpushとpullをしてみます。今回は私の業務用マシンを使ったので、Mac OS X + Docker-Machine + boot2docker + VirtualBoxという組み合わせで動いています。
CA用証明書のコピー
まずは、またも下記URLを参考にしてCA用証明書をコピーします。URL先で示されているコピー先は、Dockerホスト内のディレクトリなので注意してください。
ちなみに、上記だとコピーしてdockerデーモン再起動すれば良いみたいに書かれておりますが、コピーした後に私の環境で docker push
を実行すると以下のようなエラーが出ました。
FATA[0000] Error: invalid registry endpoint https://hostname:5000/v0/: unable to ping registry endpoint https://hostname:5000/v0/ v2 ping attempt failed with error: Get https://hostname:5000/v2/: x509: certificate signed by unknown authority v1 ping attempt failed with error: Get https://hostname:5000/v1/_ping: x509: certificate signed by unknown authority. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry hostname:5000` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/hostname:5000/ca.crt
この時点でCA用証明書がコピーされていることは確認しています。Dockerホスト内の実行ログを確認してもこのパスにあるCA用証明書がロードされていることは間違いないようです。で、社内で相談した所、ルート証明書を参照できていないのではないか、ということで、ルート証明書のリンクをCA用証明書の場所に作成してみました。
sudo ln -s /etc/ssl/certs/ca-certificates.crt /etc/docker/certs.d/hostname:5000/ca-certificates.crt
で、実行してみましたが、状況変わらず。
自己認証のサーバを信頼させる
で、色々調べてみた所、以下のURLの様なドキュメントを見つけました。DockerHubとは異なるRegistryを信頼させる設定方法とのこと。
上記URLの「Adding your own Registry certificates to DTR *2 」の「Boot2Docker 1.6.0」の箇所を見れば良さそうです。
このURLに従って設定してみた所、ちゃんと docker push
できました。
Docker RegistryとクライアントのDockerホストでイメージをやり取りする
さて、やり取りができる準備が整いましたので、実際にやり取りしてみましょう。既にローカルのDockerホスト上で作った、アプリケーションが動くイメージがあるのでそれをRegistryにpushして、別のDockerホストにpullして動かす、という所までやりたいと思います。
クライアントからイメージをpushする
既に作ってあるイメージはRegistryにpushできるタグ名になっていないため、そのままではpushできません *3 。
push用のタグ付けをする
Dockerのpushコマンドとpullコマンドは、引数に渡すタグ名のルールで取得先のレジストリやポートやバージョンまですべて解決しているようです。ルールは以下の通りです。
[host name]:[port]/[image name]/[version]
現状ではオプションで接続先のRegistryなどを指定する方法がないので、一度作ったイメージをpushする場合は、この規約に合うようにタグ付けし直す必要があるということになります。この辺り、実際の運用に入る前にアプリケーションの docker-compose.yml
の書き方だとか諸々ルールを決めておいた方が良いんじゃないかな、と感じた所。
イメージをpushする
イメージのタグ付けをすれば、後は docker push
を叩くだけです。Registryに接続して、イメージのアップロードを開始してくれます。
別のDockerホストでイメージをpullしてくる
Registryにイメージがpushされたことを確認するため、今pushしたイメージを持っていない別のDockerホストでpushしたイメージを使ってアプリケーションを動かしてみたいと思います。というわけで、おもむろに docker-machine create
します。で、新しいDockerホストのためにCA認証用の各種設定をしてあげます。
後は docker pull
を叩くだけです。タグはもちろん先述のルールで。イメージのダウンロードが始まります。ダウンロードが完了したら、 docker images
を叩いてみてください。クライアントのDockerホストに指定したタグのイメージがリストアップされているはずです。pullしてきたイメージの実行も問題なくできました。
クライアント側の設定面倒くさい(主に頻度的に)
これ、すごい面倒な感じでして、Dockerホストの起動中は良いんですけど、立ち上げる度にやり直さないと行けないんですね。主にDocker-Machine + VirtualBoxドライバの場合の問題なんですけど、業務用マシンとかだと電源落として帰ったりもするので、よけいに面倒です *4 。
というわけで・・・
クライアント側の設定が面倒すぎたのでこんなの作りました。
基本的には上述の各種URLの内容を一括でやるだけのシェルスクリプト群です。
これから
しばらくは、技術的な検証というよりも、社内での運用をどうして行くかになりそうなので、公開できる話が少なくなりそうな予感。ちょっとかっこいいやつ作りたい。