序章

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

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

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

前提条件

  • Ubuntu20.04初期サーバーセットアップガイドに従ってセットアップされた2台のUbuntu20.04サーバー。 sudo 非rootユーザーとファイアウォール。 1台のサーバーはプライベートDockerレジストリをホストし、もう1台はクライアントサーバーになります。
  • Ubuntu 20.04にDockerをインストールして使用する方法のステップ1と2に従って、両方のサーバーにDockerをインストールします。
  • Ubuntu 20.04にDockerComposeをインストールして使用する方法のステップ1に従って、hostサーバーにDockerComposeをインストールします。
  • Ubuntu 20.04 にNginxをインストールする方法の手順に従って、hostサーバーにNginxをインストールします。
  • Ubuntu 20.04チュートリアルでLet’sEncryptを使用してNginxを保護する方法に従って、プライベートDockerレジストリのサーバーでLet’sEncryptを使用してNginxを保護します。 ステップ4で、すべてのトラフィックをHTTPからHTTPSにリダイレクトしてください。
  • プライベートDockerレジストリに使用しているサーバーに解決されるドメイン名。 これは、Let’sEncryptの前提条件の一部として設定します。 このチュートリアルでは、これを次のように参照します。 your_domain.

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

コマンドラインのDockerは、コンテナーを起動してテストするときに役立ちますが、複数のコンテナーが並行して実行される大規模なデプロイメントでは扱いにくいことがわかります。

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

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

構成をというディレクトリに保存します docker-registry メインサーバー上。 次のコマンドを実行して作成します。

  1. mkdir ~/docker-registry

そこに移動します:

  1. cd ~/docker-registry

次に、というサブディレクトリを作成します data、レジストリがその画像を保存する場所:

  1. mkdir data

と呼ばれるファイルを作成して開きます docker-compose.yml 実行することによって:

  1. nano docker-compose.yml

Dockerレジストリの基本インスタンスを定義する次の行を追加します。

〜/ docker-registry / docker-compose.yml
version: '3'

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

まず、最初のサービスに名前を付けます registry、およびその画像をに設定します registry、 バージョン 2. 次に、 ports、ポートをマッピングします 5000 ホストからポートへ 5000 コンテナの。 これにより、ポートにリクエストを送信できます 5000 サーバー上で、リクエストをレジストリに転送します。

の中に environment セクションでは、 REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY に可変 /data、データを保存するボリュームを指定します。 次に、 volumes セクションでは、マップします /data ホストファイルシステム上のディレクトリ /data パススルーとして機能するコンテナ内。 データは実際にはホストのファイルシステムに保存されます。

ファイルを保存して閉じます。

これで、次のコマンドを実行して構成を開始できます。

  1. docker-compose up

レジストリコンテナとその依存関係がダウンロードされ、開始されます。

Output
Creating network "docker-registry_default" with the default driver Pulling registry (registry:2)... 2: Pulling from library/registry e95f33c60a64: Pull complete 4d7f2300f040: Pull complete 35a7b7da3905: Pull complete d656466e1fe8: Pull complete b6cb731e4f93: Pull complete Digest: sha256:da946ca03fca0aade04a73aa94b54ff0dc614216bdd1d47585f97b4c1bdaa0e2 Status: Downloaded newer image for registry:2 Creating docker-registry_registry_1 ... done Attaching to docker-registry_registry_1 registry_1 | time="2021-03-18T12:32:59.587157744Z" 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.11.2 instance.id=119fe50b-2bb6-4a8d-902d-dfa2db63fc2f service=registry version=v2.7.1 registry_1 | time="2021-03-18T12:32:59.587912733Z" level=info msg="redis not configured" go.version=go1.11.2 instance.id=119fe50b-2bb6-4a8d-902d-dfa2db63fc2f service=registry version=v2.7.1 registry_1 | time="2021-03-18T12:32:59.598496488Z" level=info msg="using inmemory blob descriptor cache" go.version=go1.11.2 instance.id=119fe50b-2bb6-4a8d-902d-dfa2db63fc2f service=registry version=v2.7.1 registry_1 | time="2021-03-18T12:32:59.601503005Z" level=info msg="listening on [::]:5000" go.version=go1.11.2 instance.id=119fe50b-2bb6-4a8d-902d-dfa2db63fc2f service=registry version=v2.7.1 ...

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

押すことができます CTRL+C その実行を停止します。

このステップでは、ポートでリッスンしているDockerレジストリを開始するDockerCompose構成を作成しました 5000. 次の手順では、ドメインで公開し、認証を設定します。

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

前提条件の一部として、ドメインでHTTPSを有効にしました。 保護されたDockerレジストリをそこで公開するには、ドメインからレジストリコンテナにトラフィックを転送するようにNginxを構成するだけで済みます。

すでに設定しています /etc/nginx/sites-available/your_domain サーバー構成を含むファイル。 次のコマンドを実行して、編集用に開きます。

  1. sudo nano /etc/nginx/sites-available/your_domain

既存のものを探す location ブロック:

/ etc / nginx / sites-available / your_domain
...
location / {
  ...
}
...

トラフィックをポートに転送する必要があります 5000、レジストリがトラフィックをリッスンする場所。 また、レジストリに転送されるリクエストにヘッダーを追加します。これにより、リクエスト自体に関するサーバーからの追加情報が提供されます。 の既存のコンテンツを置き換えます location 次の行でブロックします。

/ etc / nginx / sites-available / your_domain
...
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 if ブロックは、リクエストのユーザーエージェントをチェックし、Dockerクライアントのバージョンが1.5を超えていること、およびそれが1.5を超えていないことを確認します。 Go アクセスしようとしているアプリケーション。 これについての詳細は、 nginx DockerのレジストリNginxガイドのヘッダー構成。

完了したら、ファイルを保存して閉じます。 Nginxを再起動して変更を適用します。

  1. sudo systemctl restart nginx

エラーが発生した場合は、追加した構成を再確認してください。

Nginxがポートのレジストリコンテナにトラフィックを適切に転送していることを確認するには 5000、 それを実行します:

  1. docker-compose up

次に、ブラウザウィンドウで、ドメインに移動して、 v2 エンドポイント、そのように:

https://your_domain/v2

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

{}

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

Output
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 出力の最後の行は、コンテナーが要求を正常に処理したことを意味します。

プレス CTRL+C その実行を停止します。

ポートフォワーディングを設定したので、次にレジストリのセキュリティを向上させます。

ステップ3—認証の設定

Nginxを使用すると、管理するサイトのHTTP認証を設定できます。これを使用して、Dockerレジストリへのアクセスを制限できます。 これを実現するには、で認証ファイルを作成します htpasswd 受け入れられるユーザー名とパスワードの組み合わせを追加します。

あなたは得ることができます htpasswd インストールすることによるユーティリティ apache2-utils パッケージ。 実行してこれを行います:

  1. sudo apt install apache2-utils -y

認証ファイルを資格情報とともに保存します ~/docker-registry/auth. 次のコマンドを実行して作成します。

  1. mkdir ~/docker-registry/auth

そこに移動します:

  1. cd ~/docker-registry/auth

最初のユーザーを作成し、置き換えます username 使用するユーザー名を使用します。 The -B フラグは、 bcrypt Dockerが必要とするアルゴリズム:

  1. htpasswd -Bc registry.password username

プロンプトが表示されたらパスワードを入力すると、資格情報の組み合わせがに追加されます registry.password.

注:ユーザーを追加するには、前のコマンドを実行せずに再実行してください -c、新しいファイルを作成します。

  1. htpasswd -B registry.password username

クレデンシャルのリストが作成されたので、編集します docker-compose.yml 作成したファイルを使用してユーザーを認証するようにDockerに注文します。 次のコマンドを実行して、編集用に開きます。

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

強調表示された行を追加します。

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

HTTP認証の使用を指定する環境変数を追加し、ファイルへのパスを指定しました htpasswd 作成した。 為に REGISTRY_AUTH、指定しました htpasswd 使用している認証方式である値として設定します REGISTRY_AUTH_HTPASSWD_PATH 認証ファイルのパスへ。 REGISTRY_AUTH_HTPASSWD_REALM の名前を意味します htpasswd レルム。

また、マウントしました ./auth レジストリコンテナ内でファイルを使用できるようにするディレクトリ。 ファイルを保存して閉じます。

これで、認証が正しく機能することを確認できます。 まず、メインディレクトリに移動します。

  1. cd ~/docker-registry

次に、以下を実行してレジストリを実行します。

  1. docker-compose up

ブラウザで、ドメインのページを更新します。 ユーザー名とパスワードの入力を求められます。

クレデンシャルの有効な組み合わせを提供すると、空のJSONオブジェクトが表示されます。

{}

これは、正常に認証され、レジストリへのアクセスを取得したことを意味します。 を押して終了します CTRL+C.

これでレジストリが保護され、認証後にのみアクセスできるようになりました。 次に、自動的に起動することで再起動に耐えながら、バックグラウンドプロセスとして実行するように構成します。

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

Docker Composeに常に実行を継続するように指示することにより、システムが起動するたびに、またはシステムがクラッシュした後に、レジストリコンテナが確実に起動するようにすることができます。 開ける docker-compose.yml 編集用:

  1. nano docker-compose.yml

下に次の行を追加します registry ブロック:

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

設定 restart コンテナが再起動後も存続することを常に保証します。 完了したら、ファイルを保存して閉じます。

これで、渡すことでバックグラウンドプロセスとしてレジストリを開始できます -d:

  1. docker-compose up -d

レジストリをバックグラウンドで実行すると、SSHセッションを自由に閉じることができ、レジストリは影響を受けません。

Dockerイメージのサイズが非常に大きい可能性があるため、Nginxがアップロードに受け入れる最大ファイルサイズを増やします。

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

イメージをレジストリにプッシュする前に、レジストリが大きなファイルのアップロードを処理できることを確認する必要があります。

Nginxでのファイルアップロードのデフォルトのサイズ制限は 1m、これはDockerイメージにはほとんど十分ではありません。 それを上げるには、次の場所にあるメインのNginx構成ファイルを変更します。 /etc/nginx/nginx.conf. 次のコマンドを実行して、編集用に開きます。

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

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

/etc/nginx/nginx.conf
...
http {
        client_max_body_size 16384m;
        ...
}
...

The client_max_body_size パラメータがに設定されました 16384m、最大アップロードサイズを16GBにします。

完了したら、ファイルを保存して閉じます。

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

  1. sudo systemctl restart nginx

Nginxが転送をブロックしたりエラーを発生させたりすることなく、大きな画像をDockerレジストリにアップロードできるようになりました。

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

Docker Registryサーバーが稼働し、大きなファイルサイズを受け入れるようになったので、イメージをサーバーにプッシュしてみてください。 すぐに利用できる画像がないため、 ubuntu テストするパブリックDockerレジストリであるDockerHubからのイメージ。

2番目のクライアントサーバーから、次のコマンドを実行してダウンロードします。 ubuntu イメージを作成して実行し、シェルにアクセスします。

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

The -i-t フラグを使用すると、コンテナへのインタラクティブなシェルアクセスが可能になります。

入ったら、というファイルを作成します SUCCESS 実行することによって:

  1. touch /SUCCESS

このファイルを作成することにより、コンテナをカスタマイズしました。 後でそれを使用して、まったく同じコンテナを使用していることを確認します。

次のコマンドを実行して、コンテナシェルを終了します。

  1. exit

次に、カスタマイズしたコンテナから新しいイメージを作成します。

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

これで新しいイメージがローカルで利用可能になり、新しいコンテナレジストリにプッシュします。 まず、ログインする必要があります:

  1. docker login https://your_domain

プロンプトが表示されたら、このチュートリアルのステップ3で定義したユーザー名とパスワードの組み合わせを入力します。

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

Output
... Login Succeeded

ログインしたら、作成したイメージの名前を変更します。

  1. docker tag test-image your_domain/test-image

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

  1. docker push your_domain/test-image

次のような出力が表示されます。

Output
The push refers to a repository [your_domain/test-image] 420fa2a9b12e: Pushed c20d459170d8: Pushed db978cae6a05: Pushed aeb3f02e9374: Pushed latest: digest: sha256:88e782b3a2844a8d9f0819dc33f825dde45846b1c5f9eb4870016f2944fe6717 size: 1150

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

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

イメージをプライベートレジストリにプッシュしたので、そこからプルしてみます。

メインサーバーで、前に設定したユーザー名とパスワードを使用してログインします。

  1. docker login https://your_domain

引っ張ってみてください test-image 実行することによって:

  1. docker pull your_domain/test-image

Dockerはイメージをダウンロードする必要があります。 次のコマンドでコンテナを実行します。

  1. docker run -it your_domain/test-image /bin/bash

次のコマンドを実行して、存在するファイルを一覧表示します。

  1. ls

が表示されます SUCCESS 以前に作成したファイルで、作成したものと同じイメージであることを確認します。

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

次のコマンドを実行して、コンテナシェルを終了します。

  1. exit

画像のプッシュとプルをテストしたので、カスタム画像の保存に使用できる安全なレジストリの設定が完了しました。

結論

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