Ubuntu 14.04でプライベートDockerレジストリを設定する方法

前書き

Dockerは、サーバーを展開するための優れたツールです。 Dockerには、Dockerハブと呼ばれるパブリックレジストリもあり、Dockerイメージを保存します。 Dockerでは、作成したDockerをDocker Hubに無料でアップロードできますが、アップロードしたものはすべて公開されます。 これは、プロジェクトに最適なオプションではない場合があります。

このガイドでは、独自のプライベートDockerレジストリを設定して保護する方法を示します。 このチュートリアルの終わりまでに、カスタムDockerイメージをプライベートレジストリにプッシュし、別のホストから安全にイメージをプルできるようになります。

このチュートリアルでは、独自のアプリケーションのコンテナ化については説明しませんが、展開を保存できるレジストリの作成方法についてのみ説明します。 (レジストリではなく)Docker自体の使用を開始する方法を学びたい場合は、How To Install and Use Docker: Getting Startedチュートリアルを読むことをお勧めします。

このチュートリアルは、Ubuntu 14.04を実行しているレジストリサーバーとレジストリクライアントの両方でテストされていますが、他のDebianベースのディストリビューションでも機能する可能性があります。 また、Dockerレジストリのバージョン2.0もカバーしています。

Dockerの概念

これまでにDockerを使用したことがない場合は、Dockerの主要な概念をいくつか見ていく価値があります。 既にDockerを使用しており、独自のレジストリの実行を開始する方法を知りたい場合は、次のセクションに進んでください。

Dockerの使用方法の復習については、優れたDocker Cheat Sheetをご覧ください。

Dockerの中核は、アプリケーションとオペレーティングシステム自体から実行するために必要な依存関係を分離する方法です。 これを可能にするために、Dockerはcontainersimagesを使用します。 Dockerイメージは、基本的にファイルシステムのテンプレートです。 Dockerイメージを実行すると、このファイルシステムのインスタンスがライブになり、Dockerコンテナー内のシステムで実行されます。 デフォルトでは、このコンテナは元の画像自体やDockerを実行しているホストのファイルシステムに触れることはできません。 自己完結型の環境です。

コンテナで行った変更はすべてそのコンテナ自体に保持され、元の画像には影響しません。 これらの変更を保持することにした場合は、コンテナをDockerイメージに「コミット」できます(docker commitコマンドを使用)。 つまり、元のコンテナ(またはイメージ)に影響を与えることなく、古いコンテナのコンテンツで始まる新しいコンテナを生成できます。 gitに精通している場合、ワークフローは非常に似ているように見えるはずです。任意のコンテナから新しいブランチ(Docker用語ではイメージ)を作成できます。 イメージの実行は、git checkoutの実行に少し似ています。

類推を続けると、プライベートDockerレジストリの実行は、DockerイメージのプライベートGitリポジトリの実行に似ています。

前提条件

このチュートリアルを完了するには、次のものが必要です。

  • 2 Ubuntu 14.04ドロップレット:プライベートDockerレジストリ用とDockerクライアント用

  • 各ドロップレットに対するsudo権限を持つroot以外のユーザー(Initial Server Setup with Ubuntu 14.04は、これを設定する方法を説明しています)。

  • How To Install and Use Docker Compose on Ubuntu 14.04の指示に従ってインストールされたDockerおよびDocker Compose

  • プライベートDockerレジストリのドロップレットに解決されるドメイン名

[[step-1 -—- installing-package-for-added-security]] ==ステップ1—セキュリティを強化するためのパッケージのインストール

Dockerレジストリのセキュリティを設定するには、Docker Composeを使用するのが最適です。 このようにして、1つのコンテナでDockerレジストリを簡単に実行し、別のコンテナでNginxにセキュリティと外部との通信を処理させることができます。 前提条件セクションから既にインストールされているはずです。

Nginxを使用してセキュリティを処理するため、レジストリにアクセスするユーザー名とパスワードの組み合わせのリストを保存する場所も必要です。 Nginxが理解できるパスワードハッシュを簡単に生成できるhtpasswdユーティリティを含むapache2-utilsパッケージをインストールします。

sudo apt-get -y install apache2-utils

[[step-2 -—- installing-and-configuring-the-docker-registry]] ==ステップ2—Dockerレジストリのインストールと構成

Dockerコマンドラインツールは、1つまたは2つのDockerコンテナーの起動と管理に最適ですが、Dockerコンテナー内で実行されるほとんどのアプリは単独では存在しません。 ほとんどのアプリを完全にデプロイするには、いくつかのコンポーネントを並行して実行する必要があります。 たとえば、ほとんどのウェブアプリケーションは、アプリのコードを提供するウェブサーバー、PHPやRuby(with 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

ファイルに次の内容を追加します。

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ビットは、そのコンテナー内の/dataディレクトリが実際にホストマシン上の/dataにマップされる必要があることをDockerに通知しています。 したがって、最終的な結果として、Dockerレジストリのデータはすべてローカルマシンの~/docker-registry/dataに格納されます。

先に進み、すべてを正常に実行するために起動します。

cd ~/docker-registry
docker-compose up

画面上に多数のダウンロードバーが表示されます(これは、Docker自身のDocker Registryから実際のDockerレジストリイメージをダウンロードする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レジストリコンテナーをシャットダウンします。

[[step-3 -—- setting-up-an-nginx-container]] ==ステップ3—Nginxコンテナの設定

これらのセキュリティ問題の修正に取り掛かりましょう。 最初のステップは、Nginxのコピーを別のDockerコンテナー内にセットアップし、それをDockerレジストリコンテナーにリンクすることです。

Nginx設定を保存するディレクトリを作成することから始めましょう。

mkdir ~/docker-registry/nginx

ここで、~/docker-registryディレクトリにあるdocker-compose.ymlファイルを再度開きます。

nano docker-compose.yml

次をファイルの上部に貼り付けます。

docker-compose.yml

nginx:
  image: "nginx:1.9"
  ports:
    - 5043:443
  links:
    - registry:registry
  volumes:
    - ./nginx/:/etc/nginx/conf.d:ro

これにより、公式のNginxイメージに基づいて新しいDockerコンテナーが作成されます。 ここで興味深いのは、linksセクションです。 Dockerコンテナから別のコンテナへの「リンク」を自動的に設定します。 Nginxコンテナが起動すると、registryコンテナが最終的に持つ実際のIPアドレスに関係なく、ホスト名registryregistryコンテナに到達できます。 (舞台裏では、Dockerは実際にnginxコンテナの/etc/hostsファイルにエントリを挿入してregistryコンテナのIPを通知しています)。

volumes:セクションは、registryコンテナーに対して行ったものと似ています。 この場合、Dockerコンテナ内ではなくホストマシンでNginxに使用する設定ファイルを保存する方法を提供します。 最後の:roは、Nginxコンテナがホストファイルシステムへの読み取り専用アクセスのみを持つ必要があることをDockerに通知するだけです。

完全なdocker-compose.ymlファイルは次のようになります。

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を実行すると、2つのコンテナーが同時に開始されます。1つはDockerレジストリ用で、もう1つはNginx用です。

ただし、これが機能する前にNginxを構成する必要があるため、新しいNginx構成ファイルを作成しましょう。

registry.confファイルを作成します。

nano ~/docker-registry/nginx/registry.conf

以下をファイルにコピーします。

~/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ポートに別のリクエストを行います。 すべてが正しく設定されている場合、NginxはリクエストをDockerレジストリにプロキシするため、出力はどちらの場合も同じになります(この記事の執筆時点では、Dockerは空のjsonオブジェクト「{}」を返します)。

最初に、Dockerレジストリに直接HTTP要求を行います。

curl http://localhost:5000/v2/

この記事の執筆時点では、Dockerは空のjsonオブジェクトを返しているため、次のように表示されます。

Output{}

次に、HTTP要求をNginxポートに送信します。

curl http://localhost:5043/v2/

同じ出力が表示されるはずです。

Output{}

正常に動作している場合は、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はHTTPリクエストをDockerレジストリに正常にプロキシしました。

先に進み、docker-composeターミナルでCTRL-Cをもう一度押して、Dockerコンテナーをシャットダウンします。

[[step-4 -—- setting-up-authentication]] ==ステップ4—認証の設定

Nginxはリクエストを適切にプロキシしているので、Dockerレジストリにアクセスできるユーザーを制御できるように、HTTP認証を設定します。 これを行うには、以前にインストールしたhtpasswdユーティリティを使用してApache形式の認証ファイルを作成し(Nginxも読み取ることができます)、それにユーザーを追加します。

次のように最初のユーザーを作成し、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

ファイルの中央までスクロールすると、次のような行が表示されます。

~/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で始まる行のコメントを解除します。 これは次のようになります。

~/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;

これで、Dockerレジストリにプロキシされるすべてのリクエストに対してHTTP基本認証を有効にするようNginxに指示し、作成したパスワードファイルを使用するように指示しました。

コンテナーを再起動して、認証が機能しているかどうかを確認しましょう。

cd ~/docker-registry
docker-compose up

前のカールテストを繰り返します。

curl http://localhost:5043/v2/

不正であることを訴えるメッセージが表示されるはずです。

Output of curl
401 Authorization Required

401 Authorization Required


nginx/1.9.7

次に、前に作成したユーザー名とパスワードをcurlリクエストに追加してみます。

curl http://USERNAME:PASSWORD@localhost:5043/v2/

以前と同じ出力、つまり空のjsonオブジェクト{}が得られるはずです。 docker-composeターミナルにも同じregistry_出力が表示されます。

先に進み、docker-composeターミナルでCTRL-Cを使用して、Dockerコンテナーをシャットダウンします。

[[step-5 -—- setting-up-ssl]] ==ステップ5—SSLの設定

この時点で、HTTP基本認証が機能するNginxの背後でレジストリが稼働しています。 ただし、接続は暗号化されていないため、セットアップはまだあまり安全ではありません。 以前に作成したNginx構成ファイル内のコメント化されたSSL行に気付いたかもしれません。

それらを有効にしましょう。 まず、編集のためにNginx構成ファイルを開きます。

nano ~/docker-registry/nginx/registry.conf

矢印キーを使用して移動し、次の行を探します。

~/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の値をドメイン名に変更します。 完了すると、ファイルの上部は次のようになります。

~/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;

ファイルを保存してください。 NginxはSSLを使用するように構成され、SSL証明書とキーファイルをそれぞれ/etc/nginx/conf.d/domain.crt/etc/nginx/conf.d/domain.keyで検索します。 以前にdocker-compose.ymlファイルで設定したマッピングにより、Nginxコンテナの/etc/nginx/conf.d/パスはホストマシンのフォルダ~/docker-registry/nginx/に対応するため、証明書ファイルをそこに配置します。

すでにSSL証明書を設定しているか、購入を計画している場合は、証明書とキーファイルをregistry.confssl_certificatessl_certificate_key)にリストされているパスにコピーするだけです。

free signed SSL certificateを取得することもできます。

それ以外の場合は、自己署名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で“Common Name” make sure to type in the domain or IP of your serverを入力するように求められたら。

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

[.warning]#Warning:このDockerレジストリに接続するすべてのマシンに対して、この手順を繰り返す必要があります。 Ubuntu 14.04クライアントでこれを行う方法の説明は、Step 9 — Accessing Your Docker Registry from a Client Machine
#にリストされています。

[[step-6 -—- testing-ssl]] ==ステップ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/

[。注意]##

Note:自己署名証明書を使用している場合、curlから次のエラーが表示されます。

curl: (60) SSL certificate problem: self signed certificate

-kオプションを使用して、curlnotにピアで検証するように指示します。

curl -k https://USERNAME:PASSWORD@[YOUR-DOMAIN]:5043/v2/

たとえば、設定したユーザーとパスワードがsammytestで、SSL証明書がwww.example.com用である場合、次のように入力します。

curl https://sammy:[email protected]:5043/v2/

すべてがうまくいけば、curlは空のjsonオブジェクト{}を出力し、docker-compose端末は通常のregistry_出力を出力します。

そうでない場合は、SSLステップとNginx構成ファイルを再確認して、すべてが正しいことを確認します。

この時点で、SSL経由で認証と暗号化を提供しているNginxサーバーの背後で機能するDockerレジストリ2.0が稼働しています。 外部からのポート5043へのアクセスを許可するようにファイアウォールが構成されている場合は、任意のマシンdocker login https://<YOURDOMAIN>からこのDockerレジストリにログインし、前のセクションで設定したユーザー名とパスワードを入力できるはずです。 。

[[step-7 -—- setting-ssl-port-to-443]] ==ステップ7—SSLポートを443に設定する

完了する前に、さらにいくつかの手順を実行します。ポートを変更して、443(オプション)の標準SSLポートを使用し、起動時にこのコンテナーのセットを開始するようにdocker-composeを設定します。

まず、これまで使用してきた非標準ポート5043ではなく、ポート443(SSLの標準ポート)でリッスンするように、Docker化されたNginxコンテナーをセットアップします。 ただし、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は次のようになります。

~/docker-registry/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

[.note]#Note:rootユーザーのみが1024未満のポートをリッスンできます。 今回はdocker-composeコマンドでsudoを使用して、NginxがデフォルトのSSLポート443で実行できるようにする必要があることに注意してください。

docker-composeが通常どおり起動するのがわかります。

ドメイン名を使用して別のcurlテストを試してみましょう。今回は、URLで:5043を指定しません。

curl https://:@YOUR-DOMAIN/v2/

すべてがうまくいけば、docker-composeターミナルに通常のregistry_出力が表示されるはずです。 また、別のマシンからこの同じcurlコマンドを実行して、ポート443が外部に公開されていることを確認することもできます。

次のステップに進む前に、先に進み、docker-composeターミナルでCTRL-Cを使用してDockerコンテナーをシャットダウンします。

[[step-8 -—- starting-docker-registry-as-a-service]] ==ステップ8—Dockerレジストリをサービスとして開始する

すべてが良好に見える場合は、先に進んでUpstartスクリプトを作成し、システムが起動するたびにDockerレジストリが起動するようにします。

まず、既存のコンテナを削除し、Dockerレジストリをシステム全体の場所に移動して、その権限をルートに変更します。

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スクリプトを作成します(UpstartにDockerコンテナーを適切に監視させるのは少し注意が必要です。このUpstartスクリプトの機能について詳しく知りたい場合は、this blog postを確認してください)。

/etc/init/docker-registry.conf

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スクリプトの詳細については、this tutorialをお読みください。

以下を実行して、新しい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を使用してログファイルを「ライブウォッチ」しましょう(起動ログはrootユーザーとして書き込まれるため、sudoが必要です)。

sudo tail -f /var/log/upstart/docker-registry.log

通常のregistry_出力が表示されます。 別の端末またはマシンから先に進み、今ではおなじみのcurlテストを実行します。

curl https://:@[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" "-"

[[step-9 -—- accessing-your-docker-registry-from-a-client-machine]] ==ステップ9—クライアントマシンからDockerレジストリにアクセスする

別のマシンからDockerレジストリにアクセスするには、最初に以前に作成したSSL証明書を新しいクライアントマシンに追加します。 必要なファイルは~/docker-registry/nginx/devdockerCA.crtにあります。

新しいマシンに直接コピーするか、以下の手順を使用してコピーして貼り付けることができます。

registry serverで、証明書を表示します。

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-----

その出力をクリップボードにコピーし、クライアントマシンに接続します。

client machineで、証明書ディレクトリを作成します。

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レジストリが稼働しています。 レジストリにプッシュするテストイメージを作成しましょう。

[[step-10 -—- publish-to-your-private-docker-registry]] ==ステップ10—プライベートDockerレジストリに公開する

これで、プライベートDockerレジストリにイメージを公開する準備ができましたが、最初にイメージを作成する必要があります。 Docker Hubからのubuntuイメージに基づいて単純なイメージを作成します。

client machineから、小さな空のイメージを作成して、新しいレジストリにプッシュします。

docker run -t -i ubuntu /bin/bash

ダウンロードが完了すると、Dockerプロンプトが表示されます。 SUCCESSというファイルを作成して、ファイルシステムに簡単な変更を加えましょう。

touch /SUCCESS

Dockerコンテナーを終了します。

exit

変更をコミットします。

docker commit $(docker ps -lq) test-image

このコマンドは、すでに実行されているイメージと行った変更に基づいて、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

最初に画像のローカル名を使用し、次に追加するタグを使用していることに注意してください。 タグはnotを使用し、ドメイン、ポート、画像名のみを使用します。

これで、そのイメージをレジストリにプッシュできます。 今回はタグ名のみを使用しています:

docker push [YOUR-DOMAIN]/test-image

これには、レジストリサーバーへのアップロードに時間がかかります。 次のようなもので終わる出力が表示されます。

Output of docker pushlatest: digest: sha256:5ea1cfb425544011a3198757f9c6b283fa209a928caabe56063f85f3402363b4 size: 8008

[[step-11 -—- pull-from-your-docker-registry]] ==ステップ11—Dockerレジストリからプル

すべてが正常に機能することを確認するために、元のサーバー(Dockerレジストリをインストールした場所)に戻り、クライアントからプッシュしたばかりの画像を取得します。 これを3番目のサーバーからテストすることもできます。

テストプルサーバーにDockerがインストールされていない場合は、手順6に戻り、インストール手順(3番目のサーバーの場合は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コンテナをプッシュおよびプルしました。

ハッピードッキング!

Related