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

著者はhttps://www.brightfunds.org/organizations/apache-software-foundation[Apache Software Foundation]を選択して、https://do.co/w4do-cta [Donationsの書き込み]の一部として寄付を受け取りましたプログラム。

前書き

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

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

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

前提条件

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

  • Ubuntu 18.04初期サーバーセットアップガイドに従って、2つのUbuntu 18.04サーバーをセットアップし、sudo non- rootユーザーとファイアウォール。 1つのサーバーがプライベートDockerレジストリをホストし、もう1つのサーバーが*クライアント*サーバーになります。

  • Docker-Composeをインストールする方法に従って、両方のサーバーにインストールされたDockerおよびDocker-Compose Ubuntu 18.04]チュートリアル。 Docker Composeをインストールするには、このチュートリアルの最初のステップを完了するだけです。 このチュートリアルでは、前提条件の一部としてDockerをインストールする方法について説明します。

  • Nginxは、https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-18-04 [Ubuntu 18.04にNginxをインストールする方法]に従ってプライベートDockerレジストリサーバーにインストールされます。

  • Nginxは、https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu- 18-04 [暗号化してNginxを保護する方法]。 手順4ですべてのトラフィックをHTTPからHTTPSにリダイレクトするようにしてください。

  • プライベートDockerレジストリに使用しているサーバーに解決されるドメイン名。 これをLet’s Encryptの前提条件の一部として設定します。

手順1-Dockerレジストリのインストールと構成

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

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

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

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

mkdir ~/docker-registry && cd $_
mkdir data

テキストエディタを使用して、 `+ docker-compose.yml +`設定ファイルを作成します:

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

`+ environment `セクションは、パス ` / data `を使用してDocker Registryコンテナの環境変数を設定します。 Docker Registryアプリケーションは起動時にこの環境変数をチェックし、その結果、データを ` / data +`フォルダーに保存し始めます。

ただし、 `+ volumes:-./data:/ data `行を含めたため、Dockerはそのコンテナの ` / data `ディレクトリをレジストリサーバーの ` / data `にマップし始めます。 最終的な結果として、Dockerレジストリのデータはすべて、レジストリサーバーの `〜/ docker-registry / data +`に保存されます。

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

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

docker-compose up

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

Output of docker-compose upStarting 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

このチュートリアルの後半で、「+ HTTP秘密が提供されていません+」という警告メッセージに対処します。 出力は、コンテナが起動していることを示しています。 出力の最後の行は、ポート「5000」でのリスニングが正常に開始されたことを示しています。

デフォルトでは、Docker Composeは入力を待機したままなので、 `+ CTRL + C +`を押してDocker Registryコンテナーをシャットダウンします。

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

ステップ2-Nginxポート転送のセットアップ

Nginxを使用してDockerレジストリサーバーにHTTPSが既に設定されているため、Nginxからポート「5000」へのポート転送を設定できるようになりました。 このステップを完了すると、レジストリに直接アクセスできます。

Let’s EncryptでNginxを保護する方法前提条件として、サーバー設定を含む `+ / etc / nginx / sites-available / +`ファイルをすでに設定している。

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

sudo nano /etc/nginx/sites-available/

既存の `+ 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;
}
...

`+ $ http_user_agent `セクションは、クライアントのDockerバージョンが ` 1.5 `より上であることを確認し、 ` UserAgent `が ` Go `アプリケーションではないことを確認します。 レジストリのバージョン「+2.0」を使用しているため、古いクライアントはサポートされていません。 詳細については、https://docs.docker.com/registry/recipes/nginx/#setting-things-up [Docker’s Registry Nginx guide]で `+ nginx +`ヘッダー設定を見つけることができます。

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

sudo service nginx restart

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

cd ~/docker-registry
docker-compose up

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

https:///v2

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

{}

端末には、次のような出力が表示されます。

Output of docker-compose upregistry_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"

最後の行から、ブラウザーからリクエストを送信したエンドポイントである「+ / v2 / 」に対して「 GET 」リクエストが行われたことがわかります。 コンテナは、ポート転送からのリクエストを受け取り、 ` {} `のレスポンスを返しました。 出力の最後の行にあるコード「+200」は、コンテナがリクエストを正常に処理したことを意味します。

ポート転送を設定したので、レジストリのセキュリティの改善に進むことができます。

ステップ3-認証のセットアップ

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

以下を実行して、 `+ htpasswd +`パッケージをインストールできます。

sudo apt install apache2-utils

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

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

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

htpasswd -Bc registry.password

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

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

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

docker-compose.yml

version: '3'

services:
 registry:
   image: registry:2
   ports:
   - "5000:5000"
   environment:



     REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
   volumes:

     - ./data:/data

`+ REGISTRY_AUTH `には、使用している認証スキームである ` htpasswd `を指定し、 ` REGISTRY_AUTH_HTPASSWD_PATH `を認証ファイルのパスに設定しました。 最後に、「 REGISTRY_AUTH_HTPASSWD_REALM 」は「 htpasswd +」レルムの名前を示します。

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

docker-compose up

ブラウザウィンドウで、「+ https:/// v2 +」を開きます。

「+」と対応するパスワードを入力すると、「 {} +」が再び表示されます。 基本認証のセットアップを確認しました。正しいユーザー名とパスワードを入力した後にのみレジストリが結果を返しました。 これでレジストリが保護され、レジストリの使用を継続できます。

ステップ4-サービスとしてのDocker Registryの開始

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

nano docker-compose.yml

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

docker-compose.yml

...
 registry:

...

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

docker-compose up -d

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

ステップ5-Nginxのファイルアップロードサイズの増加

画像をレジストリにプッシュする前に、レジストリが大きなファイルのアップロードを処理できることを確認する必要があります。 Dockerは大きな画像のアップロードを別々のレイヤーに分割しますが、「+ 1GB 」を超える場合があります。 デフォルトでは、Nginxにはファイルのアップロード時に「 1MB 」の制限があるため、「 nginx 」の設定ファイルを編集し、最大ファイルアップロードサイズを「 2GB +」に設定する必要があります。

sudo nano /etc/nginx/nginx.conf

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

/etc/nginx/nginx.conf

...
http {

       ...
}
...

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

sudo service nginx restart

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

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

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

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

docker run -t -i ubuntu /bin/bash

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

touch /SUCCESS

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

exit

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

変更をコミットします。

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

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

docker login https://

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

docker tag test-image /test-image

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

docker push /test-image

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

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

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

ステップ7-プライベートDockerレジストリからのプル

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

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

docker login https://

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

docker pull /test-image

Dockerはイメージをダウンロードし、プロンプトに戻ります。 レジストリサーバーでイメージを実行すると、先ほど作成した `+ SUCCESS +`ファイルが表示されます:

docker run -it /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イメージを公開しました。 概要で述べたように、https://docs.travis-ci.com/user/docker/ [TravisCI]または同様のCIツールを使用して、プライベートレジストリへの直接プッシュを自動化することもできます。 Dockerとレジストリをワークフローに活用することにより、コードを含むイメージが、実稼働中または開発中のどのマシンでも同じ動作になることを保証できます。 Dockerファイルの作成の詳細については、プロセスを説明するhttps://docs.docker.com/develop/develop-images/dockerfile_best-practices/[Dockerチュートリアル]をご覧ください。

Related