概要
今回は、会社であったり、個人開発であったりいろいろとDocker のイメージを管理する
registory を使用することがあると思いますが、
その際のprivate registry を自分で作る時のハマりどころ(自分が実際にハマったこと)を
備忘録的にまとめておこうと思います。
達成したいこと
タイトルに書いている通り、
TLS認証(公開鍵認証)と、Basic認証(パスワード認証)を持った
Docker Private Registry を作ることを目標にします。
また、Registryはクラウド上のインスタンスにおくことを想定し、
Ubuntu環境でRegistry の設置、
実際にRegistryにイメージをとりにいくのもUbuntu環境から取得する、という構成にします。
今回はこのような流れで執り行います。
- クラウドのインスタンス上にdocker image registry を立ち上げる(TLS無し、Basic認証無し)
- Opensslを用いて、自己証明のTLSを準備する
- 鍵などを所定の場所に置き、サービスを再起動する
- 鍵をクライアントの環境にコピーする
- クライアントからRegistryに接続を試みる
この時に慣れていないと色々とハマりどころがあると思うので、そこを中心に書きたいと思います。
手順1 Ubuntu環境にDockerをサクッとインストール
まっさらなUbuntu18とか20の環境をクラウド上に作ったら、
上のリンクのコマンドを実行し、Docker, Docker-compose をワンライナーで
インストールしましょう。
手順2 Docker image registry 認証無しバージョンを を立ち上げてみる
私は基本的に
この記事を参考にさせていただきました。
ここからはこの記事の内容に沿ってレジストリを立ち上げます。
まずはTLS無し、Basic認証無しでいいのでレジストリを立ち上げてみましょう。
手順3 Basic認証のためのユーザ名とパスワードをhtpasswdを使って登録する
htpasswd -cB auth/htpasswd username
とすると、auth/htpasswd
に、username というユーザネームの認証情報が登録されます。
パスワードはコンソールで聞かれますので、設定します。
このauthフォルダは、レジストリを作る時にコンテナにマウントされ、
クライアントからのログイン時のBasic認証に使用されます。
このコマンドは初回に使用するコマンドであり、
2回目以降は
htpasswd -B auth/htpasswd user2
などとします。
下を参考にしました。
https://qiita.com/masakuni-ito/items/3d951035884184632b99
https://qiita.com/kimihito_/items/3fb0788f28e5b51bcaa9
手順4 OpenSSLを用いて鍵を準備する
このコマンドを実行し、必要な鍵 ca.key, ca.crtを作成します。
この時、上の記事とは異なる場所が少しあり、それは
-addext
の部分です。
openssl コマンドを実行した時、
上のような画面が出ると思いますが、Common Name にはドメイン名
つまりRegistry を作るサーバのグローバルIPを書きます。
しかし、-addext 無しだと、
後にクライアントサイドから、Registry にDocker login しようとした際、
Error response from daemon: Get "https://xxx.xxx.xxx/v2/": x509: certificate relies on legacy Common Name field, use SANs instead
となります。
SANについては調べれば
この記事など色々と解説されています。
結論としては、Common Name にドメイン名を指定するのではなく、
下のコマンドのように -addext を用いてSANを指定するようにしましょう。
sudo openssl req -newkey rsa:2048 -nodes -sha256 -keyout certs/ca.key -x509 -days 3650 -out certs/ca.crt -addext "subjectAltName = IP:xxx.xxx.xxx"
鍵の生成が済んだら、certs の下にca.key, ca.crt が生成されています。
それらを以下のコマンドで所定の場所に移動させ、
ca-certificates、docker の再起動を行います。
sudo cp certs/ca.* /usr/share/ca-certificates/
sudo update-ca-certificates
sudo vim /etc/ca-certificates.conf
sudo systemctl restart docker
ここで、3行目で sudo vim /etc/ca-certificates.conf
としていますが、最後の行に
/usr/share/ca-certificates/
からみた相対的なca.crtへのパスを表記します。
上のコマンドに従ったのであれば、ca.crt は/usr/share/ca-certificates/
直下に格納されていますから、
/etc/ca-certificates.conf
の最終行に
ca.crt
と追加すれば大丈夫です。
手順5 レジストリを立ち上げる
以上が準備できれば、
version: '3'
services:
registry:
image: registry:2
volumes:
- ./auth:/auth
- ./certs:/certs
- registry:/var/lib/registry
ports:
- "443:443"
environment:
- REGISTRY_AUTH=htpasswd
- REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm"
- REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
- REGISTRY_HTTP_ADDR=0.0.0.0:443
- REGISTRY_HTTP_TLS_CERTIFICATE=/certs/ca.crt
- REGISTRY_HTTP_TLS_KEY=/certs/ca.key
- REGISTRY_STORAGE_DELETE_ENABLED=true
restart: always
web:
depends_on:
- registry
image: parabuzzle/craneoperator:latest
ports:
- "8000:80"
environment:
- REGISTRY_HOST=registry
- REGISTRY_PORT=443
- REGISTRY_PROTOCOL=https
- SSL_VERIFY=false
- REGISTRY_PUBLIC_URL=20.210.192.115
- REGISTRY_USERNAME=username
- REGISTRY_PASSWORD=password
- USERNAME=username
- PASSWORD=password
- REGISTRY_ALLOW_DELETE=true
restart: always
volumes:
registry:
上のcompose に従い、docker-compose up -d
でレジストリを立ち上げることが可能です。
手順6 鍵をクライアントの環境にコピーする
鍵(ca.crt, ca.key)をクライアントサイドにコピーします。
これはscp などを用いて行います。
私の場合、クライアントサイドのホームディレクトリの
certs フォルダ内にca.crt, ca.keyを配置しました。
手順7 クライアントサイドの鍵を所定の位置に起き、Dockerなどを再起動する
これは手順3と同じ手順なのですが、下のコマンドをクライアントサイドで実行します。
sudo cp certs/ca.* /usr/share/ca-certificates/
sudo vim /etc/ca-certificates.conf
vim コマンドにより追記する内容は、
手順4と同じで、
/usr/share/ca-certificates/
からみた相対的なca.crtへのパスを表記します。
上のコマンドに従ったのであれば、ca.crt は/usr/share/ca-certificates/
直下に格納されていますから、
/etc/ca-certificates.conf
の最終行に
ca.crt
と追加すれば大丈夫です。
sudo update-ca-certificates
sudo systemctl restart docker
手順8 クライアントサイドからレジストリにアクセスしてみる
以上が整ったら、クライアントサイドから
docker login xxx.xxx.xxx
xxx.xxx.xxxはレジストリが置いてあるインスタンスのIP
として、ログインできるか確かめましょう。
注意
ここで、
Error response from daemon: Get https://20.210.192.115/v2/: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "Internet Widgits Pty Ltd")
と言うようなエラーとなったときは、以下を試しましょう。
sudo vim /etc/docker/daemon.json
{ "insecure-registries":["xxx.xxx.xxx:yyyy"] }
として、xxx.xxx.xxx:yyy のところには、レジストリのIPを書きます。
ログインできたのであれば、docker push, docker pull
などが行えるはずです。お疲れ様でした。
まとめ
今回はdocker private registry
を、SSL認証、Basic認証込みで構築してみました。
また、いくつかの記事に沿って実行しようとした結果うまくいかずに詰まったところ、
特にSANSの設定のところ、について言及しました。
もし同じエラーで悩んでいる方がいたら助けになれば幸いです。
今回はこの辺で。