CentOS 7 に Docker Registry プライベートリポジトリをローカルインストールして認証を追加する

はじめに

公式の Docker Hub はパブリックイメージを管理するのに優れた場所であり、必要なイメージを見つけたり、自身のイメージをプッシュしたりできます。しかし、場合によっては独自のプライベートイメージリポジトリが必要になることがあります。これはオープンソースソフトウェアの Registry を使用することで実現できます。

Registry のコードは GitHub 上に2種類あります:古いコードベースと新しいコードベースです。古いコードは Python で記述されており、プルおよびプッシュのパフォーマンスに問題があり、バージョン 0.9.1 以降は非推奨 (deprecated) となり、開発は継続されていません。バージョン 2.0 からは新しいコードベースで開発が行われ、Go 言語で記述され、イメージ ID の生成アルゴリズムやレジストリ上のイメージ保存構造が変更され、プルおよびプッシュの効率が大幅に最適化されています。現在、Docker Registry は v2 にアップグレードされており、最新の Docker は v1 をサポートしていません。Registry v2 は Go 言語で記述され、パフォーマンスとセキュリティの面で多くの最適化が施され、イメージの保存形式が再設計されています。

プライベートリポジトリを使用する利点は数多くあります:

  1. ネットワーク帯域幅を節約:各イメージを中央レジストリからダウンロードするのではなく、プライベートリポジトリからのみダウンロードすれば済みます。
  2. イメージリソースの活用:社内で使用するイメージをローカルのプライベートリポジトリにプッシュし、社内の関係者が利用できるようにします。

環境準備

環境: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

タグ: Docker Registry v2 CentOS 7 nginx HTTPS

5月24日 08:26 投稿