序章

Docker Registry は、Dockerコンテナイメージの保存と配信を管理するアプリケーションです。 レジストリはコンテナイメージを一元化し、開発者のビルド時間を短縮します。 Dockerイメージは、仮想化を通じて同じランタイム環境を保証しますが、イメージの構築には多大な時間の投資が必要になる場合があります。 たとえば、Dockerを使用するために依存関係とパッケージを別々にインストールするのではなく、開発者は必要なすべてのコンポーネントを含むレジストリから圧縮イメージをダウンロードできます。 さらに、開発者は、 TravisCI などの継続的インテグレーションツールを使用してイメージをレジストリにプッシュすることを自動化し、本番および開発中にイメージをシームレスに更新できます。

Dockerには、カスタムDockerイメージをホストできる無料のパブリックレジストリ Docker Hub もありますが、イメージを公開したくない場合があります。 通常、イメージにはアプリケーションの実行に必要なすべてのコードが含まれているため、プロプライエタリソフトウェアを使用する場合はプライベートレジストリを使用することをお勧めします。

このチュートリアルでは、独自のプライベートDockerレジストリを設定して保護します。 Docker Compose を使用して、Dockerアプリケーションを実行するための構成を定義し、Nginxを使用してサーバートラフィックをHTTPSから実行中のDockerコンテナーに転送します。 このチュートリアルを完了すると、カスタムDockerイメージをプライベートレジストリにプッシュし、リモートサーバーからイメージを安全にプルできるようになります。

前提条件

このガイドを開始する前に、次のものが必要です。

  • Ubuntu18.04初期サーバーセットアップガイドに従ってセットアップされた2つのUbuntu18.04サーバー(sudo非rootユーザーとファイアウォールを含む)。 1つのサーバーはプライベートDockerレジストリをホストし、もう1つのサーバーはクライアントサーバーになります。
  • DockerとDocker-Composeを両方のサーバーにインストールするには、 How to Install Docker-Compose on Ubuntu18.04チュートリアルに従ってください。 Docker Composeをインストールするには、このチュートリアルの最初のステップを完了するだけです。 このチュートリアルでは、前提条件の一部としてDockerをインストールする方法について説明します。
  • Ubuntu 18.04にNginxをインストールする方法に従って、プライベートDockerレジストリサーバーにNginxをインストールします。
  • Let’s EncryptでNginxを保護する方法に従って、プライベートDockerレジストリ用にサーバー上でLet’sEncryptで保護されたNginx。 手順4で、すべてのトラフィックをHTTPからHTTPSにリダイレクトしてください。
  • プライベートDockerレジストリに使用しているサーバーに解決されるドメイン名。 これは、Let’sEncryptの前提条件の一部として設定します。

ステップ1—Dockerレジストリのインストールと構成

Dockerコマンドラインツールは、1つまたは2つのDockerコンテナーを起動および管理するのに役立ちますが、完全にデプロイするには、Dockerコンテナー内で実行されるほとんどのアプリケーションで他のコンポーネントを並行して実行する必要があります。 たとえば、多くのWebアプリケーションは、アプリケーションのコードを提供するNginxなどのWebサーバー、PHPなどの解釈されたスクリプト言語、およびMySQLなどのデータベースサーバーで構成されています。

Docker Composeを使用すると、1つ書くことができます .yml 各コンテナの構成と、コンテナが相互に通信するために必要な情報を設定するためのファイル。 その後、を使用することができます docker-compose アプリケーションを構成するすべてのコンポーネントにコマンドを発行するコマンドラインツール。

Docker Registryはそれ自体が複数のコンポーネントを備えたアプリケーションであるため、DockerComposeを使用して構成を管理します。 レジストリのインスタンスを開始するには、 docker-compose.yml レジストリがデータを保存する場所を定義するファイル。

プライベートDockerレジストリをホストするために作成したサーバーで、 docker-registry ディレクトリに移動し、作成します data 次のコマンドを使用するサブフォルダー:

  1. mkdir ~/docker-registry && cd $_
  2. mkdir data

テキストエディタを使用して、 docker-compose.yml 構成ファイル:

  1. nano docker-compose.yml

Dockerレジストリの基本構成を説明する次のコンテンツをファイルに追加します。

docker-compose.yml
version: '3'

services:
  registry:
    image: registry:2
    ports:
    - "5000:5000"
    environment:
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    volumes:
      - ./data:/data

The environment セクションは、Dockerレジストリコンテナに環境変数をパスで設定します /data. Docker Registryアプリケーションは、起動時にこの環境変数をチェックし、その結果、データを /data フォルダ。

ただし、 volumes: - ./data:/data 行、Dockerはマップを開始します /data そのコンテナ内のディレクトリ /data レジストリサーバー上。 最終結果は、Dockerレジストリのデータがすべてに保存されることです。 ~/docker-registry/data レジストリサーバー上。

The ports セクション、構成付き 5000:5000、ポートをマップするようにDockerに指示します 5000 サーバー上でポートする 5000 実行中のコンテナ内。 これにより、ポートにリクエストを送信できます 5000 サーバー上で、リクエストをレジストリアプリケーションに転送します。

これで、Docker Composeを起動して、セットアップを確認できます。

  1. docker-compose up

DockerがDocker自身のレジストリからDockerレジストリイメージをダウンロードしていることを示すダウンロードバーが出力に表示されます。 1〜2分以内に、次のような出力が表示されます(バージョンは異なる場合があります)。

Output of docker-compose up
Starting docker-registry_registry_1 ... done Attaching to docker-registry_registry_1 registry_1 | time="2018-11-06T18:43:09Z" 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." go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2 registry_1 | time="2018-11-06T18:43:09Z" level=info msg="redis not configured" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2 registry_1 | time="2018-11-06T18:43:09Z" level=info msg="Starting upload purge in 20m0s" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2 registry_1 | time="2018-11-06T18:43:09Z" level=info msg="using inmemory blob descriptor cache" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2 registry_1 | time="2018-11-06T18:43:09Z" level=info msg="listening on [::]:5000" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2

あなたは対処します No HTTP secret provided このチュートリアルの後半にある警告メッセージ。 出力は、コンテナーが開始中であることを示しています。 出力の最後の行は、ポートでのリッスンが正常に開始されたことを示しています 5000.

デフォルトでは、Docker Composeは入力を待機したままになるため、 CTRL+C Dockerレジストリコンテナをシャットダウンします。

ポートでリッスンする完全なDockerレジストリを設定しました 5000. この時点で、手動で起動しない限り、レジストリは起動しません。 また、Docker Registryには認証メカニズムが組み込まれていないため、現在は安全ではなく、完全に公開されています。 次の手順では、これらのセキュリティ上の懸念に対処します。

ステップ2—Nginxポートフォワーディングの設定

Nginxを使用してDockerレジストリサーバーにHTTPSを設定しました。これは、Nginxからポートへのポート転送を設定できることを意味します。 5000. この手順を完了すると、example.comからレジストリに直接アクセスできます。

Let’s Encrypt の前提条件でNginxを保護する方法の一部として、すでに /etc/nginx/sites-available/example.com サーバー構成を含むファイル。

このファイルをテキストエディタで開きます。

  1. sudo nano /etc/nginx/sites-available/example.com

既存のものを探す location ライン。 次のようになります。

/etc/nginx/sites-available/example.com
...
location / {
  ...
}
...

トラフィックをポートに転送する必要があります 5000、レジストリが実行される場所。 また、レジストリへの要求にヘッダーを追加する必要があります。これにより、各要求と応答でサーバーからの追加情報が提供されます。 の内容を削除します location セクションを作成し、そのセクションに次のコンテンツを追加します。

/etc/nginx/sites-available/example.com
...
location / {
    # 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;
    }

    proxy_pass                          http://localhost:5000;
    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;
}
...

The $http_user_agent セクションは、クライアントのDockerバージョンが上にあることを確認します 1.5、および UserAgent ではありません Go 応用。 バージョンを使用しているので 2.0 レジストリの中で、古いクライアントはサポートされていません。 詳細については、 nginx Docker’sRegistryNginxガイドのヘッダー構成。

ファイルを保存して終了します。 Nginxを再起動して変更を適用します。

  1. sudo service nginx restart

Nginxがトラフィックをポートに転送していることを確認できます 5000 レジストリを実行することによって:

  1. cd ~/docker-registry
  2. docker-compose up

ブラウザウィンドウで、次のURLを開きます。

https://example.com/v2

空のJSONオブジェクトが表示されます。または:

{}

ターミナルでは、次のような出力が表示されます。

Output of docker-compose up
registry_1 | time="2018-11-07T17:57:42Z" level=info msg="response completed" go.version=go1.7.6 http.request.host=cornellappdev.com http.request.id=a8f5984e-15e3-4946-9c40-d71f8557652f http.request.method=GET http.request.remoteaddr=128.84.125.58 http.request.uri="/v2/" http.request.useragent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0.2 Safari/604.4.7" http.response.contenttype="application/json; charset=utf-8" http.response.duration=2.125995ms http.response.status=200 http.response.written=2 instance.id=3093e5ab-5715-42bc-808e-73f310848860 version=v2.6.2 registry_1 | 172.18.0.1 - - [07/Nov/2018:17:57:42 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0.2 Safari/604.4.7"

最後の行から、 GET リクエストが行われました /v2/、ブラウザからリクエストを送信したエンドポイントです。 コンテナは、ポートフォワーディングからの要求を受信し、次の応答を返しました。 {}. コード 200 出力の最後の行は、コンテナーが要求を正常に処理したことを意味します。

ポートフォワーディングを設定したので、レジストリのセキュリティの向上に進むことができます。

ステップ3—認証の設定

Nginxプロキシリクエストを適切に使用すると、HTTP認証を使用してレジストリを保護し、Dockerレジストリにアクセスできるユーザーを管理できるようになります。 これを実現するには、で認証ファイルを作成します htpasswd それにユーザーを追加します。 HTTP認証は、レジストリが使用するHTTPS接続を介して、すばやくセットアップして保護します。

あなたはインストールすることができます htpasswd 以下を実行してパッケージ化します。

  1. sudo apt install apache2-utils

次に、認証資格情報を保存するディレクトリを作成し、そのディレクトリに移動します。 $_ この場合、前のコマンドの最後の引数に展開されます ~/docker-registry/auth:

  1. mkdir ~/docker-registry/auth && cd $_

次に、次のように最初のユーザーを作成します。 username 使用するユーザー名を使用します。 The -B フラグは指定します bcrypt 暗号化。デフォルトの暗号化よりも安全です。 プロンプトが表示されたら、パスワードを入力します。

  1. htpasswd -Bc registry.password username

注:ユーザーを追加するには、-cオプションを指定せずに前のコマンドを再実行します( c 作成用です):

  1. htpasswd registry.password username

次に、編集します docker-compose.yml 作成したファイルを使用してユーザーを認証するようにDockerに指示するファイル。

  1. cd ~/docker-registry
  2. nano docker-compose.yml

環境変数とボリュームを追加できます auth/ 編集して作成したディレクトリ docker-compose.yml ユーザーを認証する方法をDockerに指示するファイル。 次の強調表示されたコンテンツをファイルに追加します。

docker-compose.yml
version: '3'

services:
  registry:
    image: registry:2
    ports:
    - "5000:5000"
    environment:
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    volumes:
      - ./auth:/auth
      - ./data:/data

為に REGISTRY_AUTH、指定しました htpasswd、使用している認証方式であり、設定します REGISTRY_AUTH_HTPASSWD_PATH 認証ファイルのパスへ。 ついに、 REGISTRY_AUTH_HTPASSWD_REALM の名前を意味します htpasswd レルム。

これで、レジストリを実行し、ユーザーにユーザー名とパスワードの入力を求めるプロンプトが表示されることを確認することで、認証が正しく機能することを確認できます。

  1. docker-compose up

ブラウザウィンドウで、 https://example.com/v2.

入った後 username および対応するパスワードが表示されます {} もう一度。 基本認証の設定を確認しました。レジストリは、正しいユーザー名とパスワードを入力した後にのみ結果を返しました。 これでレジストリが保護され、引き続きレジストリを使用できます。

ステップ4—サービスとしてのDockerレジストリの開始

システムが起動するたびにレジストリが確実に起動するようにする必要があります。 予期しないシステムクラッシュが発生した場合は、サーバーの再起動時にレジストリが再起動することを確認する必要があります。 開く docker-compose.yml:

  1. nano docker-compose.yml

次のコンテンツ行を下に追加します registry::

docker-compose.yml
...
  registry:
    restart: always
...

レジストリをバックグラウンドプロセスとして開始できます。これにより、レジストリを終了できます。 ssh セッションし、プロセスを永続化します。

  1. docker-compose up -d

レジストリをバックグラウンドで実行すると、ファイルアップロード用にNginxを準備できるようになります。

ステップ5—Nginxのファイルアップロードサイズを増やす

イメージをレジストリにプッシュする前に、レジストリが大きなファイルのアップロードを処理できることを確認する必要があります。 Dockerは大きな画像のアップロードを別々のレイヤーに分割しますが、それらが終了することもあります 1GB. デフォルトでは、Nginxには次の制限があります 1MB ファイルのアップロード時に、構成ファイルを編集する必要があります nginx 最大ファイルアップロードサイズをに設定します 2GB.

  1. sudo nano /etc/nginx/nginx.conf

を見つける http セクションを追加し、次の行を追加します。

/etc/nginx/nginx.conf
...
http {
        client_max_body_size 2000M;
        ...
}
...

最後に、Nginxを再起動して、構成の変更を適用します。

  1. sudo service nginx restart

Nginxエラーなしで大きな画像をDockerレジストリにアップロードできるようになりました。

ステップ6—プライベートDockerレジストリへの公開

これで、プライベートDockerレジストリにイメージを公開する準備が整いましたが、最初にイメージを作成する必要があります。 このチュートリアルでは、に基づいて簡単な画像を作成します ubuntu DockerHubからのイメージ。 Docker Hubは、パブリックにホストされているレジストリであり、アプリケーションをすばやくDocker化するために利用できる多くの事前構成されたイメージがあります。 を使用して ubuntu イメージ、レジストリへのプッシュとプルをテストします。

クライアントサーバーから、小さな空のイメージを作成して、新しいレジストリにプッシュします。 -i-t フラグを使用すると、コンテナへのインタラクティブなシェルアクセスが可能になります。

  1. docker run -t -i ubuntu /bin/bash

ダウンロードが完了すると、Dockerプロンプトが表示されます。次のコンテナIDに注意してください。 root@ 変化します。 と呼ばれるファイルを作成して、ファイルシステムにすばやく変更を加えます SUCCESS. 次のステップでは、このファイルを使用して、公開プロセスが成功したかどうかを判断できます。

  1. touch /SUCCESS

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

  1. exit

次のコマンドは、という新しいイメージを作成します test-image すでに実行されているイメージと行った変更に基づいています。 私たちの場合、 /SUCCESS ファイルは新しい画像に含まれています。

変更をコミットします。

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

この時点では、イメージはローカルにのみ存在します。 これで、作成した新しいレジストリにプッシュできます。 Dockerレジストリにログインします。

  1. docker login https://example.com

入力します username 以前の対応するパスワード。 次に、イメージにプッシュするために、プライベートレジストリの場所でイメージにタグを付けます。

  1. docker tag test-image example.com/test-image

新しくタグ付けされた画像をレジストリにプッシュします。

  1. docker push example.com/test-image

出力は次のようになります。

Output
The push refers to a repository [example.com/test-image] e3fbbfb44187: Pushed 5f70bf18a086: Pushed a3b5c80a4eba: Pushed 7f18b442972b: Pushed 3ce512daaf78: Pushed 7aae4540b42d: Pushed ...

レジストリがユーザー認証を処理し、認証されたユーザーがイメージをレジストリにプッシュできることを確認しました。 次に、レジストリからもイメージをプルできることを確認します。

ステップ7—プライベートDockerレジストリからプルする

レジストリサーバーに戻り、クライアントサーバーからのイメージのプルをテストできるようにします。 3番目のサーバーからこれをテストすることも可能です。

以前に設定したユーザー名とパスワードでログインします。

  1. docker login https://example.com

これで、画像をプルする準備が整いました。 前の手順でタグ付けしたドメイン名と画像名を使用します。

  1. docker pull example.com/test-image

Dockerはイメージをダウンロードし、プロンプトに戻ります。 レジストリサーバーでイメージを実行すると、次のように表示されます。 SUCCESS 以前に作成したファイルがあります:

  1. docker run -it example.com/test-image /bin/bash

bashシェル内にファイルをリストします。

  1. ls

が表示されます SUCCESS この画像用に作成したファイル:

SUCCESS  bin  boot  dev  etc  home  lib  lib64  media   mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

これで、ユーザーがカスタムイメージをプッシュおよびプルできる安全なレジストリの設定が完了しました。

結論

このチュートリアルでは、独自のプライベートDockerレジストリを設定し、Dockerイメージを公開しました。 はじめに述べたように、 TravisCI または同様のCIツールを使用して、プライベートレジストリへの直接プッシュを自動化することもできます。 Dockerとレジストリをワークフローに活用することで、コードを含むイメージが、本番環境でも開発環境でも、どのマシンでも同じ動作をするようにすることができます。 Dockerファイルの作成の詳細については、このDockerチュートリアルでプロセスを説明しています。