Ubuntu20.04でプライベートDockerレジストリを設定する方法
序章
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
メインサーバー上。 次のコマンドを実行して作成します。
- mkdir ~/docker-registry
そこに移動します:
- cd ~/docker-registry
次に、というサブディレクトリを作成します data
、レジストリがその画像を保存する場所:
- mkdir data
と呼ばれるファイルを作成して開きます docker-compose.yml
実行することによって:
- nano docker-compose.yml
Dockerレジストリの基本インスタンスを定義する次の行を追加します。
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
パススルーとして機能するコンテナ内。 データは実際にはホストのファイルシステムに保存されます。
ファイルを保存して閉じます。
これで、次のコマンドを実行して構成を開始できます。
- docker-compose up
レジストリコンテナとその依存関係がダウンロードされ、開始されます。
OutputCreating 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
サーバー構成を含むファイル。 次のコマンドを実行して、編集用に開きます。
- sudo nano /etc/nginx/sites-available/your_domain
既存のものを探す location
ブロック:
...
location / {
...
}
...
トラフィックをポートに転送する必要があります 5000
、レジストリがトラフィックをリッスンする場所。 また、レジストリに転送されるリクエストにヘッダーを追加します。これにより、リクエスト自体に関するサーバーからの追加情報が提供されます。 の既存のコンテンツを置き換えます location
次の行でブロックします。
...
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を再起動して変更を適用します。
- sudo systemctl restart nginx
エラーが発生した場合は、追加した構成を再確認してください。
Nginxがポートのレジストリコンテナにトラフィックを適切に転送していることを確認するには 5000
、 それを実行します:
- docker-compose up
次に、ブラウザウィンドウで、ドメインに移動して、 v2
エンドポイント、そのように:
https://your_domain/v2
空のJSONオブジェクトが表示されます。
{}
端末には、次のような出力が表示されます。
Outputregistry_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
パッケージ。 実行してこれを行います:
- sudo apt install apache2-utils -y
認証ファイルを資格情報とともに保存します ~/docker-registry/auth
. 次のコマンドを実行して作成します。
- mkdir ~/docker-registry/auth
そこに移動します:
- cd ~/docker-registry/auth
最初のユーザーを作成し、置き換えます username
使用するユーザー名を使用します。 The -B
フラグは、 bcrypt
Dockerが必要とするアルゴリズム:
- htpasswd -Bc registry.password username
プロンプトが表示されたらパスワードを入力すると、資格情報の組み合わせがに追加されます registry.password
.
注:ユーザーを追加するには、前のコマンドを実行せずに再実行してください -c
、新しいファイルを作成します。
- htpasswd -B registry.password username
クレデンシャルのリストが作成されたので、編集します docker-compose.yml
作成したファイルを使用してユーザーを認証するようにDockerに注文します。 次のコマンドを実行して、編集用に開きます。
- nano ~/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
レジストリコンテナ内でファイルを使用できるようにするディレクトリ。 ファイルを保存して閉じます。
これで、認証が正しく機能することを確認できます。 まず、メインディレクトリに移動します。
- cd ~/docker-registry
次に、以下を実行してレジストリを実行します。
- docker-compose up
ブラウザで、ドメインのページを更新します。 ユーザー名とパスワードの入力を求められます。
クレデンシャルの有効な組み合わせを提供すると、空のJSONオブジェクトが表示されます。
{}
これは、正常に認証され、レジストリへのアクセスを取得したことを意味します。 を押して終了します CTRL+C
.
これでレジストリが保護され、認証後にのみアクセスできるようになりました。 次に、自動的に起動することで再起動に耐えながら、バックグラウンドプロセスとして実行するように構成します。
ステップ4—サービスとしてのDockerレジストリの開始
Docker Composeに常に実行を継続するように指示することにより、システムが起動するたびに、またはシステムがクラッシュした後に、レジストリコンテナが確実に起動するようにすることができます。 開ける docker-compose.yml
編集用:
- nano docker-compose.yml
下に次の行を追加します registry
ブロック:
...
registry:
restart: always
...
設定 restart
コンテナが再起動後も存続することを常に保証します。 完了したら、ファイルを保存して閉じます。
これで、渡すことでバックグラウンドプロセスとしてレジストリを開始できます -d
:
- docker-compose up -d
レジストリをバックグラウンドで実行すると、SSHセッションを自由に閉じることができ、レジストリは影響を受けません。
Dockerイメージのサイズが非常に大きい可能性があるため、Nginxがアップロードに受け入れる最大ファイルサイズを増やします。
ステップ5—Nginxのファイルアップロードサイズを増やす
イメージをレジストリにプッシュする前に、レジストリが大きなファイルのアップロードを処理できることを確認する必要があります。
Nginxでのファイルアップロードのデフォルトのサイズ制限は 1m
、これはDockerイメージにはほとんど十分ではありません。 それを上げるには、次の場所にあるメインのNginx構成ファイルを変更します。 /etc/nginx/nginx.conf
. 次のコマンドを実行して、編集用に開きます。
- sudo nano /etc/nginx/nginx.conf
を見つける http
セクションを追加し、次の行を追加します。
...
http {
client_max_body_size 16384m;
...
}
...
The client_max_body_size
パラメータがに設定されました 16384m
、最大アップロードサイズを16GBにします。
完了したら、ファイルを保存して閉じます。
Nginxを再起動して、構成の変更を適用します。
- sudo systemctl restart nginx
Nginxが転送をブロックしたりエラーを発生させたりすることなく、大きな画像をDockerレジストリにアップロードできるようになりました。
ステップ6—プライベートDockerレジストリへの公開
Docker Registryサーバーが稼働し、大きなファイルサイズを受け入れるようになったので、イメージをサーバーにプッシュしてみてください。 すぐに利用できる画像がないため、 ubuntu
テストするパブリックDockerレジストリであるDockerHubからのイメージ。
2番目のクライアントサーバーから、次のコマンドを実行してダウンロードします。 ubuntu
イメージを作成して実行し、シェルにアクセスします。
- docker run -t -i ubuntu /bin/bash
The -i
と -t
フラグを使用すると、コンテナへのインタラクティブなシェルアクセスが可能になります。
入ったら、というファイルを作成します SUCCESS
実行することによって:
- touch /SUCCESS
このファイルを作成することにより、コンテナをカスタマイズしました。 後でそれを使用して、まったく同じコンテナを使用していることを確認します。
次のコマンドを実行して、コンテナシェルを終了します。
- exit
次に、カスタマイズしたコンテナから新しいイメージを作成します。
- docker commit $(docker ps -lq) test-image
これで新しいイメージがローカルで利用可能になり、新しいコンテナレジストリにプッシュします。 まず、ログインする必要があります:
- docker login https://your_domain
プロンプトが表示されたら、このチュートリアルのステップ3で定義したユーザー名とパスワードの組み合わせを入力します。
出力は次のようになります。
Output...
Login Succeeded
ログインしたら、作成したイメージの名前を変更します。
- docker tag test-image your_domain/test-image
最後に、新しくタグ付けされた画像をレジストリにプッシュします。
- docker push your_domain/test-image
次のような出力が表示されます。
OutputThe 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レジストリからプルする
イメージをプライベートレジストリにプッシュしたので、そこからプルしてみます。
メインサーバーで、前に設定したユーザー名とパスワードを使用してログインします。
- docker login https://your_domain
引っ張ってみてください test-image
実行することによって:
- docker pull your_domain/test-image
Dockerはイメージをダウンロードする必要があります。 次のコマンドでコンテナを実行します。
- docker run -it your_domain/test-image /bin/bash
次のコマンドを実行して、存在するファイルを一覧表示します。
- ls
が表示されます SUCCESS
以前に作成したファイルで、作成したものと同じイメージであることを確認します。
SUCCESS bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
次のコマンドを実行して、コンテナシェルを終了します。
- exit
画像のプッシュとプルをテストしたので、カスタム画像の保存に使用できる安全なレジストリの設定が完了しました。
結論
このチュートリアルでは、独自のプライベートDockerレジストリを設定し、Dockerイメージを公開しました。 はじめに述べたように、 TravisCI または同様のCIツールを使用して、プライベートレジストリへの直接プッシュを自動化することもできます。 ワークフローでDockerコンテナーを活用することで、コードを含むイメージが、本番環境でも開発環境でも、どのマシンでも同じ動作をするようにすることができます。 Dockerファイルの作成の詳細については、ベストプラクティスに関する公式ドキュメントにアクセスしてください。