はじめに
公式の Docker Hub はパブリックイメージを管理するのに優れた場所であり、必要なイメージを見つけたり、自身のイメージをプッシュしたりできます。しかし、場合によっては独自のプライベートイメージリポジトリが必要になることがあります。これはオープンソースソフトウェアの Registry を使用することで実現できます。
Registry のコードは GitHub 上に2種類あります:古いコードベースと新しいコードベースです。古いコードは Python で記述されており、プルおよびプッシュのパフォーマンスに問題があり、バージョン 0.9.1 以降は非推奨 (deprecated) となり、開発は継続されていません。バージョン 2.0 からは新しいコードベースで開発が行われ、Go 言語で記述され、イメージ ID の生成アルゴリズムやレジストリ上のイメージ保存構造が変更され、プルおよびプッシュの効率が大幅に最適化されています。現在、Docker Registry は v2 にアップグレードされており、最新の Docker は v1 をサポートしていません。Registry v2 は Go 言語で記述され、パフォーマンスとセキュリティの面で多くの最適化が施され、イメージの保存形式が再設計されています。
プライベートリポジトリを使用する利点は数多くあります:
- ネットワーク帯域幅を節約:各イメージを中央レジストリからダウンロードするのではなく、プライベートリポジトリからのみダウンロードすれば済みます。
- イメージリソースの活用:社内で使用するイメージをローカルのプライベートリポジトリにプッシュし、社内の関係者が利用できるようにします。
環境準備
環境:Docker がインストールされた CentOS 7 仮想マシン 2 台
仮想マシン1: 192.168.0.104 (Docker Registry リポジトリ)
仮想マシン2: 192.168.0.107 (Registry クライアント)
1. インターネットに接続可能であること。
2. yum リポジトリを追加すること。
二、Registry のデプロイ
1. 関連する依存パッケージのインストール
# yum install -y python-devel libevent-devel python-pip gcc xz-devel gcc-c++ openssl-devel
# pip install --upgrade pip
# pip install gunicorn pyyaml flask flask-cors rsa gevent
2. docker-registry ソースコードのクローン
# git clone https://github.com/docker/docker-registry.git
正クローン中 'docker-registry'...
remote: Counting objects: 7007, done.
remote: Total 7007 (delta 0), reused 0 (delta 0), pack-reused 7007
受信オブジェクト: 100% (7007/7007), 1.69 MiB | 34.00 KiB/s, done.
処理デルタ: 100% (4099/4099), done.
# cd docker-registry/
# cp config/config_sample.yml config/config.yml # 設定ファイルのサンプルをコピー
# vim config/config.yml # local セクションのローカルリポジトリのデータディレクトリパスを必要に応じて変更
docker-registry のインストール
# python setup.py install
エラー発生:M2Crypto のインストール時に swig コマンドがない。以下の手順で解決:
1. swig コマンドのインストール
# tar xf swig-3.0.12.tar.gz
# cd swig-3.0.12
# ./configure
......
# make && make install
....
Installation complete
2. M2Crypto のインストール
# cd ..
# tar xf M2Crypto-0.22.3.tar.gz
# cd M2Crypto-0.22.3
# vim setup.py # 次の行を追加: self.swig_opts.append('-cpperraswarn')
# python setup.py install
......
Finished processing dependencies for M2Crypto==0.22.3
3. registry のインストール
# cd ..
# python setup.py install
......
Finished processing dependencies for docker-registry==1.0.0-dev
4. ローカルリポジトリの起動
# mkdir /var/log/docker-registry/ # ログディレクトリを作成
# gunicorn --access-logfile /var/log/docker-registry/access.log --error-logfile /var/log/docker-registry/error.log -k gevent --max-requests 100 -t 3600 -b 127.0.0.1:5000 -w 1 docker_registry.wsgi:application &
[1] 54733
# 14/Dec/2017:22:55:48 +0000 WARNING: Cache storage disabled!
14/Dec/2017:22:55:48 +0000 WARNING: LRU cache disabled!
14/Dec/2017:22:55:48 +0000 DEBUG: Will return docker-registry.drivers.file.Storage
# netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1035/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 2161/master
tcp 0 0 127.0.0.1:5000 0.0.0.0:* LISTEN 54733/python
tcp6 0 0 :::22 :::* LISTEN 1035/sshd
tcp6 0 0 ::1:25 :::* LISTEN 2161/master
# curl http://127.0.0.1:5000
"\"docker-registry server\""
三、Registry サービスはローカルでのみリッスンするため、他のホストからアクセスできるよう nginx をインストールし、転送と認証を追加
1. 自己署名 HTTPS 証明書の作成
# openssl genrsa -des3 -out my.key 1024 # RSA 鍵を生成
Generating RSA private key, 1024 bit long modulus
...............................................................++++++
............++++++
e is 65537 (0x10001)
Enter pass phrase for my.key: # パスワードを入力
Verifying - Enter pass phrase for my.key: # パスワードを確認
# openssl rsa -in my.key -out nopass.key # パスワード不要の鍵ファイルを作成
Enter pass phrase for my.key:
writing RSA key
# openssl req -new -key nopass.key -out my.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:BJ
Locality Name (eg, city) [Default City]:BJ
Organization Name (eg, company) [Default Company Ltd]:LP
Organizational Unit Name (eg, section) []:LP
Common Name (eg, your name or your server's hostname) []:registry-server # 自身のドメイン名
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 -days 3650 -in my.csr -signkey nopass.key -out my.crt # 自己署名証明書を作成
Signature ok
subject=/C=CN/ST=BJ/L=BJ/O=LP/OU=LP/CN=registry-server
Getting Private key
# mkdir /etc/ssl/private/ # 鍵の格納ディレクトリを作成
# cp my.* nopass.key /etc/ssl/private/ # 指定ディレクトリにコピー
# ll /etc/ssl/private/
合計 16
-rw-r--r--. 1 root root 814 12月 14 23:01 my.crt
-rw-r--r--. 1 root root 635 12月 14 23:01 my.csr
-rw-r--r--. 1 root root 963 12月 14 23:01 my.key
-rw-r--r--. 1 root root 887 12月 14 23:01 nopass.key
2. nginx のインストールと設定
# yum install nginx httpd -y # nginx と httpd をインストール
# htpasswd -c /etc/nginx/docker-registry-htpasswd user1 # 最初のユーザーを作成
New password:
Re-type new password:
Adding password for user user1
# htpasswd /etc/nginx/docker-registry-htpasswd user2 # 2 番目のユーザーを作成(-c オプションなし)
New password:
Re-type new password:
Adding password for user user2
設定ファイルの編集
# vim /etc/nginx/conf.d/docker-registry.conf
upstream docker-registry {
server 127.0.0.1:5000;
}
server {
listen 192.168.0.104:5000;
server_name www.docker-registry.com;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
client_max_body_size 0;
chunked_transfer_encoding on;
ssl on;
ssl_certificate /etc/ssl/private/my.crt;
ssl_certificate_key /etc/ssl/private/nopass.key;
ssl_protocols TLSv1.1 TLSv1.2;
location / {
auth_basic "please Input username/password";
auth_basic_user_file /etc/nginx/docker-registry-htpasswd;
proxy_pass http://docker-registry;
}
location /_ping {
auth_basic off;
proxy_pass http://docker-registry;
}
location /v1/_ping {
auth_basic off;
proxy_pass http://docker-registry;
}
}
# setenforce 0
# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# systemctl restart nginx
クライアントでのテスト
1. hosts 解決の設定
# echo "192.168.0.104 www.docker-registry.com" >> /etc/hosts
# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.0.104 www.docker-registry.com
2. ユーザー名とパスワードを使用しない場合と使用する場合の結果
直接アクセス
# curl --insecure https://www.docker-registry.com:5000
<html>
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.12.2</center>
</body>
</html>
ユーザー名とパスワードを使用したアクセス
# curl --insecure https://user1:123456@www.docker-registry.com:5000
"\"docker-registry server\""
四、テストイメージのダウンロードとアップロード
サーバー側:
# docker pull hello-world
Using default tag: latest
Trying to pull repository docker.io/library/hello-world ...
latest: Pulling from docker.io/library/hello-world
ca4f61b1923c: Pull complete
Digest: sha256:be0cd392e45be79ffeffa6b05338b98ebb16c87b255f48e297ec7f98e123905c
テストイメージにタグを付けます (タグコマンドは既存のイメージに別名を追加し、元の名前は保持します)
# docker tag hello-world 127.0.0.1:5000/hello-world
ローカルイメージの確認
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/registry 2 177391bcf802 4 days ago 33.26 MB
127.0.0.1:5000/hello-world latest f2a91732366c 2 weeks ago 1.848 kB
docker.io/hello-world latest f2a91732366c 2 weeks ago 1.848 kB
テストイメージをプライベートリポジトリにプッシュ
# docker push 127.0.0.1:5000/hello-world
The push refers to a repository [127.0.0.1:5000/hello-world]
f999ae22f308: Image successfully pushed
Pushing tag for rev [f2a91732366c] on {http://127.0.0.1:5000/v1/repositories/hello-world/tags/latest}
クライアント側:
registry へのログイン:
# docker login www.docker-registry.com:5000
Username : user1
Password:
Login Succeeded
registry 情報の確認:
# curl --insecure https://user1:123456@www.docker-registry.com:5000/v1/search
{"num_results": 1, "query": "", "results": [{"description": "", "name": "library/hello-world"}]}
特定のイメージの検索:
# curl --insecure https://user1:123456@www.docker-registry.com:5000/v1/search?q=hello-world
{"num_results": 1, "query": "hello-world", "results": [{"description": "", "name": "library/hello-world"}]}
hello-world が library/hello-world の下にあることが確認できます。
クライアントでのダウンロード:
# docker pull www.docker-registry.com:5000/library/hello-world
Using default tag: latest
Trying to pull repository www.docker-registry.com:5000/library/hello-world ...
Pulling repository www.docker-registry.com:5000/library/hello-world
f2a91732366c: Pull complete Status: Downloaded newer image for www.docker-registry.com:5000/library/hello-world:latest
www.docker-registry.com:5000/library/hello-world: this image was pulled from a legacy registry. Important: This registry version will not be supported in future versions of docker.
# docker images # ダウンロードしたイメージの確認
REPOSITORY TAG IMAGE ID CREATED SIZE
www.docker-registry.com:5000/library/hello-world latest 1cd4a767e1b4 3 weeks ago 1.848 kB