2
1

More than 1 year has passed since last update.

Docker Private Registry + TLS認証 + Basic認証 を作る時のハマりどころを解説【10分でできる】

Last updated at Posted at 2022-07-14

概要

今回は、会社であったり、個人開発であったりいろいろと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 コマンドを実行した時、

Screen Shot 2022-07-14 at 17.36.43.png

上のような画面が出ると思いますが、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
の最終行に

/etc/ca-certificates.conf
ca.crt

と追加すれば大丈夫です。

手順5 レジストリを立ち上げる

以上が準備できれば、

docker-compose.yml

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
の最終行に

/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の設定のところ、について言及しました。

もし同じエラーで悩んでいる方がいたら助けになれば幸いです。

今回はこの辺で。

@kenmaro

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1