Ubuntu 14.04でプライベートDockerレジストリを設定する方法
Ubuntu 14.04を使用していませんか?別のバージョンまたはディストリビューションを選択してください。
紹介
Dockerはサーバーを展開するための素晴らしいツールです。DockerにはDocker画像を保存するためのDocker Hubというパブリックレジストリもあります。DockerはあなたのDockerの作品を無料でDocker Hubにアップロードできるようにしていますが、アップロードしたものはすべて公開されます。これはあなたのプロジェクトにとって最良の選択肢ではないかもしれません。
このガイドでは、自分のプライベートDockerレジストリを設定し、安全に保つ方法を示します。このチュートリアルの終わりには、カスタムDockerイメージをプライベートレジストリにプッシュし、別のホストから安全にイメージをプルできるようになります。
このチュートリアルでは、自分のアプリケーションをコンテナ化する方法ではなく、デプロイメントを保存できるレジストリの作成方法についてのみ説明しています。Docker自体の使い方(レジストリではなく)を学びたい場合は、『Dockerをインストールして使う方法:入門』のチュートリアルを読むことをお勧めします。
このチュートリアルは、Ubuntu 14.04でレジストリサーバーとレジストリクライアントの両方を実行してテストされていますが、他のDebianベースのディストリビューションでも動作する可能性があります。また、Docker Registryのバージョン2.0もカバーしています。
Dockerの概念
Dockerを使用したことがない場合は、Dockerの主要な概念をいくつか確認するのに少し時間をかける価値があります。すでにDockerを使用していて、自分のレジストリを実行する方法を知りたいだけの場合は、次のセクションに進んでください。
Dockerの使い方を復習するために、優れたDockerチートシートを見てみてください。
Dockerはその根幹において、アプリケーションとそれを実行するために必要な依存関係をオペレーティングシステム自体から切り離す方法です。これを実現するために、Dockerはコンテナとイメージを使用します。Dockerイメージは基本的にファイルシステムのテンプレートです。Dockerイメージを実行すると、このファイルシステムのインスタンスがライブになり、Dockerコンテナ内でシステム上で実行されます。デフォルトでは、このコンテナは元のイメージやDockerが実行されているホストのファイルシステムに触れることができません。これは自己完結型の環境です。
コンテナ内で行った変更は、そのコンテナ自体に保存され、元のイメージには影響しません。変更を保持したい場合は、コンテナをDockerイメージに「コミット」することができます(docker commit コマンドを使用)。これにより、元のコンテナ(またはイメージ)に影響を与えることなく、古いコンテナの内容を持つ新しいコンテナを作成できます。gitに慣れている場合は、このワークフローは非常に似ていると感じるでしょう:任意のコンテナから新しいブランチ(Docker用語ではイメージ)を作成できます。イメージを実行することは、git checkoutを行うのと少し似ています。
この比喩を続けると、プライベートのDockerレジストリを運営することは、DockerイメージのためにプライベートのGitリポジトリを運営することに似ています。
前提条件
このチュートリアルを完了するには、以下が必要です:
- 2つのUbuntu 14.04ドロップレット:一つはプライベートDockerレジストリ用、もう一つはDockerクライアント用
- 各Dropletにsudo権限を持つ非ルートユーザーを設定します(初期サーバーセットアップに関するUbuntu 14.04の説明を参照してください)。
- Ubuntu 14.04にDockerとDocker Composeをインストールする方法の指示に従ってインストールしました。
- プライベート Docker レジストリのためのドロップレットに解決されるドメイン名
ステップ1 — セキュリティ強化のためのパッケージをインストールする
Docker Registryのセキュリティを設定するには、Docker Composeを使用するのが最適です。この方法で、Docker Registryを1つのコンテナで簡単に実行し、Nginxがセキュリティと外部との通信を別のコンテナで処理できるようになります。事前準備のセクションからすでにインストールされているはずです。
私たちはセキュリティを処理するためにNginxを使用するので、レジストリにアクセスするためのユーザー名とパスワードの組み合わせのリストを保存する場所も必要です。私たちは、Nginxが理解できるパスワードハッシュを簡単に生成できるhtpasswdユーティリティを含むapache2-utilsパッケージをインストールします:
- sudo apt-get -y install apache2-utils
ステップ2 — Dockerレジストリのインストールと構成
Dockerのコマンドラインツールは、Dockerコンテナを一つや二つ起動および管理するのには便利ですが、Dockerコンテナ内で動作するほとんどのアプリは孤立して存在していません。ほとんどのアプリを完全にデプロイするには、いくつかのコンポーネントが並行して動作する必要があります。たとえば、ほとんどのWebアプリケーションは、アプリのコードを提供するWebサーバー、PHPやRuby(Railsを含む)などの解釈型スクリプト言語、MySQLのようなデータベースサーバーで構成されています。
Docker Composeは、各コンテナの設定およびコンテナ間のコミュニケーションに関する情報のために、1つの.yml構成ファイルを書くことを可能にします。そして、docker-composeコマンドラインツールを使用して、アプリケーションを構成するすべてのコンポーネントにコマンドを発行します。
Dockerレジストリ自体が複数のコンポーネントを持つアプリケーションであるため、Docker Composeを使用して設定を管理します。
基本的なレジストリを開始するには、データを保存する場所を定義するだけの設定が必要です。基本的なレジストリのインスタンスを立ち上げるための基本的なDocker Compose YAMLファイルを設定しましょう。
まず、このチュートリアルのファイルが置かれるフォルダを作成し、必要なサブフォルダもいくつか作成します。
- mkdir ~/docker-registry && cd $_
- mkdir data
お気に入りのテキストエディタを使用して、docker-compose.ymlファイルを作成してください。
- nano docker-compose.yml
次の内容をファイルに追加してください:
registry:
image: registry:2
ports:
- 127.0.0.1:5000:5000
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
- ./data:/data
ここでの興味深い点は最後です。environment セクションは、パス /data で Docker レジストリコンテナに環境変数を設定します。Docker レジストリアプリは、起動時にこの環境変数を確認し、その結果としてデータを /data フォルダに保存することを知っています。
この場合に限り、volumes: - ./data:/data の部分は、Dockerにそのコンテナ内の/dataディレクトリを実際にはホストマシンの/dataにマッピングするように指示しています。そのため、最終的な結果として、Dockerレジストリのデータはすべてローカルマシンの~/docker-registry/dataに保存されることになります。
それを始めて、すべてが整っていることを確認しましょう:
- cd ~/docker-registry
- docker-compose up
スクリーン上にダウンロードバーがいくつか表示されるのを見るでしょう(これはDockerが自社のDocker Registryから実際のDockerレジストリイメージをダウンロードしているのです)。すべてがうまくいけば、1分か2分後に次のような出力が表示されるはずです(バージョンは異なる場合があります):
Output of docker-compose upregistry_1 | time="2015-10-18T23:45:58Z" level=warning msg="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." instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="redis not configured" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="using inmemory blob descriptor cache" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="listening on [::]:5000" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="Starting upload purge in 1m0s" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
「No HTTP secret provided」というメッセージを気にしないでください。これは正常です。
素晴らしい!この時点で、すでにフル機能のDockerレジストリが稼働しており、ポート5000でリスニングしています(これはdocker-compose.ymlファイルのports:部分で設定されました)。この時点ではレジストリはあまり役に立たない状態です — 手動でレジストリを立ち上げるまで、起動しません。また、Dockerレジストリには組み込みの認証メカニズムがないため、現在は不安定で公開に完全に開放されています。
Docker Composeはデフォルトで、あなたの入力を永遠に待ち続けるので、CTRL-Cを押してDockerレジストリコンテナをシャットダウンしてください。
ステップ3 — Nginxコンテナのセットアップ
これらのセキュリティ問題の修正に取り掛かりましょう。最初のステップは、別のDockerコンテナ内にNginxのコピーをセットアップし、それを私たちのDockerレジストリコンテナにリンクすることです。
Nginxの設定を保存するためのディレクトリを作成することから始めましょう:
- mkdir ~/docker-registry/nginx
では、~/docker-registryディレクトリ内のdocker-compose.ymlファイルを再度開いてください:
- nano docker-compose.yml
ファイルの先頭に次の内容を貼り付けてください:
nginx:
image: "nginx:1.9"
ports:
- 5043:443
links:
- registry:registry
volumes:
- ./nginx/:/etc/nginx/conf.d:ro
これは公式のNginxイメージに基づいて新しいDockerコンテナを作成します。ここでの興味深い部分はlinksセクションです。これは、自動的に1つのDockerコンテナから別のDockerコンテナへの「リンク」を設定します。Nginxコンテナが起動すると、実際のIPアドレスがどうであれ、registryコンテナにホスト名registryでアクセスできるようになります。(裏ではDockerが実際にnginxコンテナの/etc/hostsファイルにregistryコンテナのIPを教えるためのエントリを挿入しています)。
volumes: セクションは、私たちが registry コンテナのために行ったことに似ています。この場合、Nginx 用の設定ファイルを Docker コンテナの内部ではなく、ホストマシンに保存する方法を提供します。最後の :ro は、Nginx コンテナがホストファイルシステムに対して読み取り専用アクセスしか持たないべきであることを Docker に伝えています。
あなたの完全な docker-compose.yml ファイルは現在次のようになります:
nginx:
image: "nginx:1.9"
ports:
- 5043:443
links:
- registry:registry
volumes:
- ./nginx/:/etc/nginx/conf.d
registry:
image: registry:2
ports:
- 127.0.0.1:5000:5000
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
- ./data:/data
コマンド docker-compose up を実行すると、Docker レジストリ用と Nginx 用の2つのコンテナが同時に起動します。
これが機能する前にNginxを設定する必要があるので、新しいNginxの設定ファイルを作成しましょう。
registry.conf ファイルを作成します:
- nano ~/docker-registry/nginx/registry.conf
次の内容をファイルにコピーしてください。
upstream docker-registry {
server registry:5000;
}
server {
listen 443;
server_name myregistrydomain.com;
# SSL
# ssl on;
# ssl_certificate /etc/nginx/conf.d/domain.crt;
# ssl_certificate_key /etc/nginx/conf.d/domain.key;
# disable any limits to avoid HTTP 413 for large image uploads
client_max_body_size 0;
# required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
chunked_transfer_encoding on;
location /v2/ {
# Do not allow connections from docker 1.5 and earlier
# docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
return 404;
}
# To add basic authentication to v2 use auth_basic setting plus add_header
# auth_basic "registry.localhost";
# auth_basic_user_file /etc/nginx/conf.d/registry.password;
# add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
proxy_pass http://docker-registry;
proxy_set_header Host $http_host; # required for docker client's sake
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900;
}
}
ファイルを保存して終了します。
これで、Nginxをインストールし、2つのDockerコンテナを1つのコマンドで起動できるようになりました。
- docker-compose up
Nginxは起動時に出力を表示しませんが、すべてがうまくいけば、あなたはregistryコンテナにプロキシするように設定されたNginxのコピーを実行していることになります。これをテストするために、curlを使って私たちのDockerレジストリに直接HTTPリクエストを送り、その後にNginxポートに別のリクエストを送ります。すべてが正しく設定されていれば、出力は両方の場合で同じになります(執筆時点でDockerは空のjsonオブジェクト「{}」を返します)なぜならNginxがリクエストをDockerレジストリにプロキシするからです。
まず、Dockerレジストリに直接HTTPリクエストを送ります:
- curl http://localhost:5000/v2/
この記事を書いている時点では、Dockerは空のjsonオブジェクトを返しますので、次のように表示されるはずです。
{}
今、NginxポートにHTTPリクエストを送信してください:
- curl http://localhost:5043/v2/
あなたは同じ出力を見るべきです。
{}
もしすべてが正しく動作しているなら、あなたの docker-compose ターミナルに以下のような出力が表示されるでしょう:
Output of docker-compose registry_1 | time="2015-08-11T10:24:53.746529894Z" level=debug msg="authorizing request" environment=development http.request.host="localhost:5043" http.request.id=55c3e2a6-4f34-4b0b-bc57-11c814b4f4d3 http.request.method=GET http.request.remoteaddr=172.17.42.1 http.request.uri="/v2/" http.request.useragent="curl/7.35.0" instance.id=55634dfc-c9e0-4ec9-9872-6f4930c17759 service=registry version=v2.0.1
registry_1 | time="2015-08-11T10:24:53.747650205Z" level=info msg="response completed" environment=development http.request.host="localhost:5043" http.request.id=55c3e2a6-4f34-4b0b-bc57-11c814b4f4d3 http.request.method=GET http.request.remoteaddr=172.17.42.1 http.request.uri="/v2/" http.request.useragent="curl/7.35.0" http.response.contenttype="application/json; charset=utf-8" http.response.duration=8.143193ms http.response.status=200 http.response.written=2 instance.id=55634dfc-c9e0-4ec9-9872-6f4930c17759 service=registry version=v2.0.1
registry_1 | 172.17.0.21 - - [11/Aug/2015:10:24:53 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "curl/7.35.0"
nginx_1 | 172.17.42.1 - - [11/Aug/2015:10:24:53 +0000] "GET /v2/ HTTP/1.1" 200 2 "-" "curl/7.35.0" "-"
もし registry_ プレフィックスのある行が見られる場合(_ の後の数字はあなたのマシンで異なる場合があります)、すべては正常であり、Nginx は Docker レジストリへの HTTP リクエストを正常にプロキシしています。
あなたの docker-compose ターミナルで再度 CTRL-C を押して、Dockerコンテナをシャットダウンしてください。
ステップ4 — 認証の設定
Nginxがリクエストを適切にプロキシしているので、Dockerレジストリへのアクセスを制御できるようにHTTP認証を設定しましょう。そのために、以前インストールしたhtpasswdユーティリティを使用して、Apache形式の認証ファイルを作成し、ユーザーを追加します。
最初のユーザーを次のように作成します。USERNAMEを使用したいユーザー名に置き換えてください:
- cd ~/docker-registry/nginx
- htpasswd -c registry.password USERNAME
プロンプトが表示されたら、このユーザーの新しいパスワードを作成してください。
将来もっとユーザーを追加したい場合は、上記のコマンドを再度実行するだけで、-cオプションを省いてください(cは作成のためのものです):
- htpasswd registry.password USERNAME
この時点で、私たちはユーザーが設定されたregistry.passwordファイルと利用可能なDockerレジストリを持っています。ユーザーを確認したい場合は、いつでもファイルを覗いて見ることができます(アクセスを取り消したいユーザーを削除することもできます)。
次に、Nginxにその認証ファイルを使用するように指示する必要があります。
~/docker-registry/nginx/registry.conf をお気に入りのテキストエディタで開いてください:
- nano ~/docker-registry/nginx/registry.conf
ファイルの中央までスクロールすると、このような行が表示されます:
To add basic authentication to v2 use auth_basic setting plus add_header
# auth_basic "registry.localhost";
# auth_basic_user_file /etc/nginx/conf.d/registry.password;
# add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
始めに、auth_basicで始まる2行と、add_headerで始まる行の先頭にある#文字を削除してコメントを外してください。すると、このように見えるはずです:
To add basic authentication to v2 use auth_basic setting plus add_header
auth_basic "registry.localhost";
auth_basic_user_file /etc/nginx/conf.d/registry.password;
add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
私たちは現在、Nginxに対してDockerレジストリにプロキシされるすべてのリクエストにHTTPベーシック認証を有効にするよう指示し、作成したパスワードファイルを使用するように設定しました。
認証が機能しているか確認するために、コンテナを再起動しましょう。
- cd ~/docker-registry
- docker-compose up
前のcurlテストを繰り返してください:
- curl http://localhost:5043/v2/
無許可であることに対して不満を述べるメッセージが届くはずです:
Output of curl<html>
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.9.7</center>
</body>
</html>
さて、前に作成したユーザー名とパスワードをcurlリクエストに追加してみてください:
- curl http://USERNAME:PASSWORD@localhost:5043/v2/
以前取得していたのと同じ出力、つまり空のJSONオブジェクト{}が得られるはずです。また、docker-composeターミナルでも同じregistry_出力が表示されるはずです。
docker-composeターミナルでCTRL-Cを使用して、Dockerコンテナをシャットダウンしてください。
ステップ5 — SSLの設定
この時点で、私たちはNginxの背後でレジストリを稼働させており、HTTP基本認証が機能しています。しかし、接続が暗号化されていないため、セットアップはまだあまり安全ではありません。以前に作成したNginxの設定ファイルにコメントアウトされたSSL行に気づいたかもしれません。
彼らを有効にしましょう。まず、Nginxの設定ファイルを編集のために開きます:
- nano ~/docker-registry/nginx/registry.conf
矢印キーを使って移動し、これらのラインを探してください:
server {
listen 443;
server_name myregistrydomain.com;
# SSL
# ssl on;
# ssl_certificate /etc/nginx/conf.d/domain.crt;
# ssl_certificate_key /etc/nginx/conf.d/domain.key;
SSLに関するコメントの下にある行の先頭にある#文字を削除してコメントを解除します。サーバー用にドメイン名を設定している場合は、server_nameの値をそのドメイン名に変更してください。作業が完了したら、ファイルの上部は次のようになります:
server {
listen 443;
server_name myregistrydomain.com;
# SSL
ssl on;
ssl_certificate /etc/nginx/conf.d/domain.crt;
ssl_certificate_key /etc/nginx/conf.d/domain.key;
ファイルを保存します。NginxはSSLの使用に設定されており、SSL証明書および秘密鍵ファイルをそれぞれ/etc/nginx/conf.d/domain.crtおよび/etc/nginx/conf.d/domain.keyで探します。以前に設定したマッピングにより、Nginxコンテナ内の/etc/nginx/conf.d/パスはホストマシンのフォルダー~/docker-registry/nginx/に対応するため、そこで証明書ファイルを配置します。
すでにSSL証明書を設定しているか、購入する予定がある場合は、証明書とキーのファイルをregistry.confに記載されたパス(ssl_certificateおよびssl_certificate_key)にコピーするだけです。
無料の署名済みSSL証明書を取得することもできます。
そうでなければ、自署のSSL証明書を使用する必要があります。
自分の証明書に署名すること
現在Dockerでは自己署名SSL証明書を使用できないため、これは通常よりも少し複雑です — システムを自分自身の証明書発行機関として機能させる必要もあります。
まず、~/docker-registry/nginxフォルダーに移動し、証明書を作成する準備をしましょう:
- cd ~/docker-registry/nginx
新しいルートキーを生成してください:
- openssl genrsa -out devdockerCA.key 2048
ルート証明書を生成します(プロンプトにはご自由に入力してください):
- openssl req -x509 -new -nodes -key devdockerCA.key -days 10000 -out devdockerCA.crt
次に、サーバー用のキーを生成します(これは私たちのNginx設定のssl_certificate_keyで参照されているファイルです):
- openssl genrsa -out domain.key 2048
今、私たちは証明書署名要求を作成する必要があります。
このコマンドを入力した後、OpenSSL はいくつかの質問に答えるように促します。最初のいくつかにはお好きな内容を書いてください。ただし、OpenSSL が「コモンネーム」と入力するように促したときには、サーバーのドメインまたはIPを入力してください。
- openssl req -new -key domain.key -out dev-docker-registry.com.csr
例えば、あなたのDockerレジストリがドメインwww.ilovedocker.comで実行される場合、入力は次のようになります:
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:www.ilovedocker.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
チャレンジパスワードを入力しないでください。
次に、証明書要求に署名する必要があります:
- openssl x509 -req -in dev-docker-registry.com.csr -CA devdockerCA.crt -CAkey devdockerCA.key -CAcreateserial -out domain.crt -days 10000
私たちが生成した証明書は、VeriSignなどの既知の証明書発行機関によって検証されていないため、このDockerレジストリを使用するクライアントに対して、これは正当な証明書であることを知らせる必要があります。これをホストマシン上でローカルに行い、Dockerレジストリサーバー自体からDockerを使用できるようにしましょう:
- sudo mkdir /usr/local/share/ca-certificates/docker-dev-cert
- sudo cp devdockerCA.crt /usr/local/share/ca-certificates/docker-dev-cert
- sudo update-ca-certificates
証明書ストアの変更を反映させるために、Dockerデーモンを再起動してください。
- sudo service docker restart
警告: このDockerレジストリに接続するすべてのマシンでこのステップを繰り返す必要があります! Ubuntu 14.04クライアント用の手順は、ステップ9 — クライアントマシンからDockerレジストリにアクセスするに記載されています。
ステップ6 — SSLのテスト
おなじみの docker-compose up コマンドを使って、私たちのDockerコンテナを立ち上げましょう:
- cd ~/docker-registry
- docker-compose up
別のターミナルからもう一度curlテストを行います(今回はhttpsを使用して、SSLの設定が正しく動作していることを確認してください)。SSLが正しく動作するためには、SSL証明書を作成する際にCommon Nameフィールドに入力したのと同じドメイン名を使用する必要があることに注意してください。
- curl https://USERNAME:PASSWORD@[YOUR-DOMAIN]:5043/v2/
注意:自己署名証明書を使用している場合、curlから以下のエラーが表示されます。
curl: (60) SSL certificate problem: self signed certificate
-kオプションを使用して、curlに相手を確認しないように指示します:
- curl -k https://USERNAME:PASSWORD@[YOUR-DOMAIN]:5043/v2/
例えば、設定したユーザー名とパスワードがsammyとtestで、SSL証明書がwww.example.comの場合、次のように入力します:
- curl https://sammy:test@www.example.com:5043/v2/
もしすべてがうまくいけば、curlは空のjsonオブジェクト{}を印刷し、あなたのdocker-composeターミナルは通常のregistry_出力を印刷します。
そうでない場合は、SSLステップとNginxの設定ファイルを再確認して、すべてが正しいことを確認してください。
この時点で、私たちはNginxサーバーの背後で動作している機能的なDockerレジストリ2.0を持っており、SSLを介して認証と暗号化を提供しています。ファイアウォールが外部からポート5043へのアクセスを許可するように構成されている場合、任意のマシンからこのDockerレジストリにログインできるはずです。docker login https://<YOURDOMAIN>を実行し、前のセクションで設定したユーザー名とパスワードを入力してください。
ステップ7 — SSLポートを443に設定する
終了する前にあといくつかの手順があります:ポートを標準のSSLポートである443に変更する(任意)と、docker-composeを設定して、このコンテナのセットを起動時に開始することです。
まず、私たちのdocker化されたNginxコンテナを設定し、これまで使用していた非標準ポート5043ではなく、SSLの標準ポート443でリッスンするようにしましょう。ただし、ポート1024未満はLinuxでは「特権」ポートとなるため、私たちはdocker-composeコンテナをrootとして実行する必要があります。
まず、テキストエディタでdocker-compose.ymlを開きます:
- nano ~/docker-registry/docker-compose.yml
Nginxセクションの下にports:セクションがあります。- 5043:443の行(これはホストマシンのポート5043をNginxコンテナ内のポート443にマッピングするものです)を- 443:443に変更してください。これにより、Nginxコンテナのポート443がホストマシンのポート443にマッピングされます。完了すると、あなたのdocker-compose.ymlは次のようになります:
nginx:
image: "nginx:1.9"
ports:
- 443:443
links:
- registry:registry
volumes:
- ./nginx/:/etc/nginx/conf.d:ro
registry:
image: registry:2
ports:
- 127.0.0.1:5000:5000
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
- ./data:/data
まだ実行中の場合は、CTRL-Cであなたのdocker-composeセッションを停止し、ポート443で再起動します:
- sudo docker-compose up
注意: ルートユーザーのみが1024未満のポートをリッスンできます。このため、NginxがデフォルトのSSLポート443で実行できるように、今回はdocker-composeコマンドにsudoを使用する必要があります。
通常通りに docker-compose が起動するのを見ることができるはずです。
私たちのドメイン名を使って別のcurlテストを試してみましょう。今回はURLに:5043を指定しません:
- curl https://<YOURUSERNAME>:<YOURPASSWORD>@YOUR-DOMAIN/v2/
すべてがうまくいけば、あなたの docker-compose ターミナルに通常の registry_ 出力が表示されるはずです。また、別のマシンから同じ curl コマンドを実行して、ポート443が外部に公開されていることを確認してみても良いでしょう。
次のステップに進む前に、docker-composeターミナルでCTRL-Cを使ってDockerコンテナをシャットダウンしてください。
ステップ8 — サービスとしてのDockerレジストリの開始
すべてが順調に見えるなら、システムが起動するたびにDockerレジストリが開始されるようにUpstartスクリプトを作成しましょう。
まず、既存のコンテナをすべて削除し、Dockerレジストリをシステム全体の場所に移動し、そのパーミッションをrootに変更しましょう:
- cd ~/docker-registry
- docker-compose rm # this removes the existing containers
- sudo mv ~/docker-registry /docker-registry
- sudo chown -R root: /docker-registry
それから、お気に入りのテキストエディタを使ってUpstartスクリプトを作成します:
- sudo nano /etc/init/docker-registry.conf
次の内容を追加して、Upstartスクリプトを作成します(Dockerコンテナを正しく監視するためのUpstartは少し厄介で、これがUpstartスクリプトが何をしているのかについての詳細が知りたい場合は、このブログ投稿をチェックしてください):
description "Docker Registry"
start on runlevel [2345]
stop on runlevel [016]
respawn
respawn limit 10 5
chdir /docker-registry
exec /usr/local/bin/docker-compose up
Upstartスクリプトについて詳しくは、このチュートリアルをお読みください。
新しいアップスタートスクリプトを実行してテストしましょう:
- sudo service docker-registry start
あなたはこのようなものを見るべきです:
docker-registry start/running, process 25303
サーバーが実行中であることを確認するには、次のコマンドを実行します:
- docker ps
出力は次のように見える必要があります(すべての名前がdockerregistry_で始まることに注意してください)
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d4b6fef0b4d1 nginx:1.9 "nginx -g 'daemon of 2 minutes ago Up 2 minutes 80/tcp, 0.0.0.0:443->443/tcp dockerregistry_nginx_1
77668352bd39 registry:2 "registry cmd/regist 2 minutes ago Up 2 minutes 127.0.0.1:5000->5000/tcp dockerregistry_registry_1
Upstartはdocker-composeコマンドの出力を/var/log/upstart/docker-registry.logに記録します。最終テストとして、tailを使ってログファイルを「ライブウォッチ」しましょう(upstartのログはrootユーザーとして記録されるため、sudoが必要です):
- sudo tail -f /var/log/upstart/docker-registry.log
通常のregistry_出力が表示されるはずです。別のターミナルやマシンから、今馴染みのあるcurlテストを実行してください:
- curl https://<YOUR_USERNAME>:<YOURPASSWORD>@[YOUR-DOMAIN]/v2/
すべてが正常に動作している場合、curlはターミナルに{}を印刷し、通常のように表示されるはずです。
registry_1 | time="2015-08-12T08:01:12.241887501Z" level=debug msg="authorizing request" environment=development http.request.host=docker.meatflavoredbeer.com http.request.id=e8d69e16-9448-4c48-afd8-57b1f1302742 http.request.method=GET http.request.remoteaddr=106.1.247.4 http.request.uri="/v2/" http.request.useragent="curl/7.37.1" instance.id=14d4727b-fda1-463f-8d0e-181f4c70cb17 service=registry version=v2.0.1
registry_1 | time="2015-08-12T08:01:12.242206499Z" level=info msg="response completed" environment=development http.request.host=docker.meatflavoredbeer.com http.request.id=e8d69e16-9448-4c48-afd8-57b1f1302742 http.request.method=GET http.request.remoteaddr=106.1.247.4 http.request.uri="/v2/" http.request.useragent="curl/7.37.1" http.response.contenttype="application/json; charset=utf-8" http.response.duration=3.359883ms http.response.status=200 http.response.written=2 instance.id=14d4727b-fda1-463f-8d0e-181f4c70cb17 service=registry version=v2.0.1
registry_1 | 172.17.0.4 - - [12/Aug/2015:08:01:12 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "curl/7.37.1"
nginx_1 | 106.1.247.4 - nik [12/Aug/2015:08:01:12 +0000] "GET /v2/ HTTP/1.1" 200 2 "-" "curl/7.37.1" "-"
ステップ 9 — クライアントマシンから Docker レジストリにアクセスする
別のマシンからDockerレジストリにアクセスするには、まず、以前に作成したSSL証明書を新しいクライアントマシンに追加します。必要なファイルは~/docker-registry/nginx/devdockerCA.crtにあります。
新しいマシンにそれを直接コピーするか、以下の手順を使ってコピー&ペーストできます:
レジストリサーバーで証明書を表示します:
- sudo cat /docker-registry/nginx/devdockerCA.crt
あなたは次のような出力を得るでしょう:
Output of sudo cat /docker-registry/nginx/devdockerCA.crt-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJANiXy7fHSPrmMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTQwOTIxMDYwODE2WhcNNDIwMjA2MDYwODE2WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuK4kNFaY3k/0RdKRK1XLj9+IrpR7WW5lrNaFB0OIiItHV9FjyuSWK2mj
ObR1IWJNrVSqWvfZ/CLGay6Lp9DJvBbpT68dhuS5xbVw3bs3ghB24TntDYhHMAc8
GWor/ZQTzjccHUd1SJxt5mGXalNHUharkLd8mv4fAb7Mh/7AFP32W4X+scPE2bVH
OJ1qH8ACo7pSVl1Ohcri6sMp01GoELyykpXu5azhuCnfXLRyuOvQb7llV5WyKhq+
SjcE3c2C+hCCC5g6IzRcMEg336Ktn5su+kK6c0hoD0PR/W0PtwgH4XlNdpVFqMST
vthEG+Hv6xVGGH+nTszN7F9ugVMxewIDAQABo1AwTjAdBgNVHQ4EFgQULek+WVyK
dJk3JIHoI4iVi0FPtdwwHwYDVR0jBBgwFoAULek+WVyKdJk3JIHoI4iVi0FPtdww
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkignESZcgr4dBmVZqDwh
YsrKeWSkj+5p9eW5hCHJ5Eg2X8oGTgItuLaLfyFWPS3MYWWMzggxgKMOQM+9o3+k
oH5sUmraNzI3TmAtkqd/8isXzBUV661BbSV0obAgF/ul5v3Tl5uBbCXObC+NUikM
O0C3fDmmeK799AM/hP5CTDehNaFXABGoVRMSlGYe8hZqap/Jm6AaKThV4g6n4F7M
u5wYtI9YDMsxeVW6OP9ZfvpGZW/n/88MSFjMlBjFfFsorfRd6P5WADhdfA6CBECG
LP83r7/MhqO06EOpsv4n2CJ3yoyqIr1L1+6C7Erl2em/jfOb/24y63dj/ATytt2H
6g==
-----END CERTIFICATE-----
その出力をクリップボードにコピーして、クライアントマシンに接続してください。
クライアントマシン上に証明書ディレクトリを作成します:
- sudo mkdir /usr/local/share/ca-certificates/docker-dev-cert
証明書ファイルを編集のために開いてください:
- sudo nano /usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt
証明書の内容を貼り付けてください。
ファイルを確認して、クライアントマシンに正しく保存されたことを確認してください。
- cat /usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt
すべてが正常に動作していれば、以前のテキストと同じものが表示されるはずです。
Output of cat /usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJANiXy7fHSPrmMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
...
...
LP83r7/MhqO06EOpsv4n2CJ3yoyqIr1L1+6C7Erl2em/jfOb/24y63dj/ATytt2H
6g==
-----END CERTIFICATE-----
今、証明書を更新してください:
- sudo update-ca-certificates
次のような出力を得るべきです(1が追加された点に注意):
Output of sudo update-ca-certificatesUpdating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.
クライアントにまだDockerがインストールされていない場合は、今すぐインストールしてください(前提条件セクションを参照)。
Dockerを再起動して、システムのCA証明書が再読み込みされるようにしてください。
- sudo service docker restart
これでクライアントマシンから Docker レジストリにログインできるようになったはずです。
- docker login https://YOUR-DOMAIN
使用していることに注意してくださいhttps://。前に設定したユーザー名とパスワードを入力してください(求められた場合はメールに何でも入力してください)。
Output of docker loginUsername: USERNAME
Password: PASSWORD
Email:
Account created. Please see the documentation of the registry http://localhost:5000/v1/ for instructions how to activate it.
次のメッセージが表示されるはずです:
Output of docker loginLogin Succeeded
この時点で、あなたのDockerレジストリは稼働しています!レジストリにプッシュするテストイメージを作成しましょう。
ステップ10 — プライベートDockerレジストリに公開する
あなたは現在、自分のプライベートDockerレジストリにイメージを公開する準備ができていますが、まずはイメージを作成する必要があります。私たちは、Docker Hubのubuntuイメージに基づいたシンプルなイメージを作成します。
あなたのクライアントマシンから、新しいレジストリにプッシュするための小さな空のイメージを作成してください。
- docker run -t -i ubuntu /bin/bash
ダウンロードが完了したら、Dockerプロンプトの中に入ります。SUCCESSという名前のファイルを作成して、ファイルシステムにすばやく変更を加えましょう:
- touch /SUCCESS
Dockerコンテナから退出する:
- exit
変更をコミットする:
- docker commit $(docker ps -lq) test-image
このコマンドは、既に実行中の画像にあなたが行った変更を加えて新しい画像を作成します。この場合、/SUCCESS ファイルの追加が新しい画像に含まれています。
この画像は現在ローカルにしか存在しないので、作成した新しいレジストリにプッシュしましょう。
前のステップでは、プライベートDockerレジストリにログインしました。まだログインしていない場合は、再度ログインしましょう(https://を使用することに注意してください):
- docker login https://YOUR-DOMAIN
以前に設定したユーザー名とパスワードを入力してください:
Username: USERNAME
Password: PASSWORD
Email:
Account created. Please see the documentation of the registry http://localhost:5000/v1/ for instructions how to activate it.
Dockerには、どのレジストリにプッシュするかを指定するための珍しいメカニズムがあります。プッシュするためには、イメージにプライベートレジストリの場所をタグ付けする必要があります。私たちのイメージをプライベートレジストリにタグ付けしましょう:
- docker tag test-image [YOUR-DOMAIN]/test-image
画像のローカル名を最初に使用し、その後に追加したいタグを記入してください。タグにはhttps://は使用せず、ドメイン、ポート、画像名のみを使用してください。
これでそのイメージを私たちのレジストリにプッシュできます。今回はタグ名のみを使用します。
- docker push [YOUR-DOMAIN]/test-image
これをレジストリサーバーにアップロードするのに少し時間がかかります。次のような出力が表示されるはずです:
Output of docker pushlatest: digest: sha256:5ea1cfb425544011a3198757f9c6b283fa209a928caabe56063f85f3402363b4 size: 8008
ステップ11 — Dockerレジストリからプルする
すべてが正常に動作していることを確認するために、元のサーバー(Dockerレジストリをインストールした場所)に戻り、クライアントからプッシュしたイメージをプルしましょう。第三のサーバーからこれをテストすることもできます。
テストプルサーバーにDockerがインストールされていない場合は、ステップ6からインストール手順(および第三のサーバーの場合はSSLの手順)に従って戻ってください。
以前に設定したユーザー名とパスワードでログインしてください。
- docker login https://[YOUR-DOMAIN]
そして今、画像を取得してください。必要なのは「タグ」画像名だけで、ドメイン名、ポート、画像名が含まれています(ただし https:// は含まれません):
- docker pull [YOUR-DOMAIN]/test-image
Dockerはいくつかのダウンロードを行い、プロンプトに戻ります。新しいマシンで画像を実行すると、以前に作成したSUCCESSファイルがあるのがわかります。
- docker run -t -i [YOUR-DOMAIN]/test-image /bin/bash
bashシェル内のファイルをリストします:
- ls
この画像のために以前作成したSUCCESSファイルを確認する必要があります:
SUCCESS bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
結論
おめでとうございます!あなたは自分のプライベートDockerレジストリを使って、初めてのDockerコンテナをプッシュおよびプルしました!
ハッピー・ドッキング!