1月 082022
 

ウェブで色々調べてみると、みんな中途半端なネタしかなくて、ウェブ UI まで含めた Docker Registry を作るのにずいぶんと苦労しました。

今回はそれをきれいさっぱりとまとめてみたいと思います。

僕はそれほど Docker に詳しくはないけど、今回のターゲットの読者 (って、いるのかな?;-) は、普段から Docker コンテナを利用していて、Docker image を自分が作成した Docker Registry で管理したい人向けです。

では始めます。今回のプラットホームは AlmaLinux 8.5 です。 docker は以下です。

$ cat /etc/os-release 
NAME="AlmaLinux"
VERSION="8.5 (Arctic Sphynx)"
ID="almalinux"
ID_LIKE="rhel centos fedora"
VERSION_ID="8.5"
PLATFORM_ID="platform:el8"
PRETTY_NAME="AlmaLinux 8.5 (Arctic Sphynx)"
ANSI_COLOR="0;34"
CPE_NAME="cpe:/o:almalinux:almalinux:8::baseos"
HOME_URL="https://almalinux.org/"
DOCUMENTATION_URL="https://wiki.almalinux.org/"
BUG_REPORT_URL="https://bugs.almalinux.org/"

ALMALINUX_MANTISBT_PROJECT="AlmaLinux-8"
ALMALINUX_MANTISBT_PROJECT_VERSION="8.5"

$ rpm -qa | grep dock
docker-scan-plugin-0.12.0-3.el8.x86_64
docker-ce-rootless-extras-20.10.12-3.el8.x86_64
docker-ce-cli-20.10.12-3.el8.x86_64
docker-ce-20.10.12-3.el8.x86_64
$

 
まず、Docker image を取ってきます。まぁ、ほぼほぼ標準のイメージです。
あ、/etc/group の docker グループに自分のアカウントを追加して上げましょう。一般ユーザ権限で docker コマンドが利用可能になります。

$ docker pull registry:2
<略>
$ docker pull konradkleine/docker-registry-frontend:v2
<略>
$ docker pull ekazakov/docker-registry-frontend
<略>

 
一番最初の docker pull は registry-server 本体です。
二番目の docker pull は ウェブで検索すると良く出てくる registry のウェブ UI です。
三番目の docker pull は registry のウェブ UI ですが、なんと、削除ボタンが付いていて不要なDocker image を削除することができます(が、僕はまだ削除したことないですf(^^;;)。

これで docker image が揃ったので docker run してみます。と、言いつつまだまだ準備ができていません。

と、いうか、最近の docker pull/push は SSL に対応しているので、プライベートで立てる registry サーパ (『リポジトリサーバ』とも言う) も SSL でアクセスできるようにして上げる必要があります。
つまり、 docker image の registry:2 を起動するためには SSL 証明書が必要なんですな。 Let’s Encrypt などでまずは証明書を準備してください。

ここ、大切な部分です。この工程をけずって『プライベートレジストリを構築するーっ!!』って、サイトが多くてイヤになる・・。非常にノイジー。古いコンテンツは消して欲しい。と、思う部分ですな。
とはいいつつ、僕のサイトにも古い記事が今でも残っているけど・・f(^^;;。

と、いうことで registry:2 イメージを run するための証明書の準備です。

# mkdir /opt/docker/repository/certs/
# cd /usr/local/etc/letsencrypt/live/running-dog.net/
# cp cert.pem /opt/docker/repository/certs/domain.crt
# cp chain.pem /opt/docker/repository/certs/ca.crt
# cp privkey.pem /opt/docker/repository/certs/domain.key

 
Let’s Encrypt で取得した証明書を /opt/docker/repository/certs/ と、いうディレクトリにそれぞれの名前で格納しました。自分のドメイン名に照らし合わせてください。
あーぅー。Linux の場合、 Let’s Encrypt のベースディレクトリはどこになるのだろう? 上記の例では FreeBSD 的に /usr/local/etc/letsencrypt/ になっていますな。自分の環境に合わせてくださいf(^^;;。

起動するときは以下のような感じ。

# mkdir /opt/docker/repository/data/
$ docker run -d -p 0.0.0.0:5000:5000 --restart=always \
 -v /opt/docker/repository/data:/var/lib/registry \
 -v /opt/docker/repository/certs:/certs \
 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
 -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
 --name registry-server \
 registry:2

 
-v でレジストリのデータを管理するディレクトリと、証明書が格納されているディレクトリをコンテナから参照できるようにしてあげます。

IP アドレスは 0.0.0.0 を指定してあげまていますが、Docker ホスト側の IP アドレスの Port:5000 に (telnet で) アクセスすると開いているかと思います。
レジストリサーバは SSL でアクセスするので、 Docker ホストの IP アドレスに FQDN を指定してあけます。今回は registry.running-dog.net にしました。view internal な DNS ゾーンファイルに設定するか /etc/hosts に指定してください。

curl で以下の要領でアクセスすれば良いです。

$ curl -k https://registry.running-dog.net:5000/v2/_catalog
$ curl -k https://registry.running-dog.net:5000/v2/centos/tags/list

 
上の curl は docker push されている、つまり、プライベートレジストリに登録されている Docker image の一覧が表示されます。
下の curl は、仮にプライベートレジストリに centos という Docker image が push されていたとすると登録してあるタグ番号一覧を返してくれます。

ここまでは Port:5000 でアクセスする registry-server 側の設定と起動方法になります。ウェブ UI がなくても上記 curl でイメージとタグ番号の確認はできます。

 
では、ここからはいよいよウェブ UI です。
インターネット上で検索してみると、docker run してサクっと registry-server に接続してその情報を表示してくれる。みたいなサイトがゴマンとありますが、あれ、みんなウソです。全然表示してくれない。なんでやねんっ!?

僕もずいぶんと悩みました。どんなにやっても ウェブ UI のコンテナから registry-server にアクセスできないっ!! ずっと、悩んでいたのですが、ようやっと、問題解決です。
先に種明かししますが、registry-server は SSL の Port:5000 にアクセスします。 URL 的には https://registry.running-dog.net:5000/ ですね。ウェブ UI 側も registry.running-dog.net の Port:5000 にアクセスするように docker run 時に指定するのですが、これは http で registry.running-dog.net の Port:5000 にアクセスしているんですね。プロトコルが https で Port:5000 にアクセスできていないので、ウェブ UI 上に registry-server の情報を表示できなかったんですね。

ここの情報について書いているサイト、ほぼ皆無です。

ウェブ UI 側のコンテナは以下のように docker run してみましょう。

$ docker run -d -p 0.0.0.0:8080:80 \
 --net reg-Segment \
 -e ENV_DOCKER_REGISTRY_HOST=registry.running-dog.net \
 -e ENV_DOCKER_REGISTRY_PORT=5000 \
 -e ENV_DOCKER_REGISTRY_USE_SSL=1 \
 -e DOCKER_REGISTRY_SCHEME \
 --name registry-web \
 ekazakov/docker-registry-frontend:latest

 
今回は削除ボタンのある ekazakov/docker-registry-frontend:latest の Docker イメージを利用してみました。
-e で環境変数を指定します。よくあるのは ENV_DOCKER_REGISTRY_HOST と ENV_DOCKER_REGISTRY_PORT です。この二つだけの指定では ウェブ UI は http で ENV_DOCKER_REGISTRY_HOST に指定したホストの ENV_DOCKER_REGISTRY_PORT に指定したポート番号にアクセスします。
この瞬間、まさに『ダメた。こりゃ。』な状態です。
https でアクセスするためには更に追加で DOCKER_REGISTRY_SCHEME と ENV_DOCKER_REGISTRY_USE_SSL=1 を指定してあげます。これで registry-server に https でアクセスしに行って、ウェブ UI に登録されている情報を表示してくれるようになります。

いやぁ・・。疲れた。あとはひたすらウェブ UI を使い込んでいくことなるかと思います。ふぅ・・。

 
と、いうことで、HTTPS でアクセスする registry-server と registry-server から HTTPS で情報を取りに行ってウェブ UI に表示してくれる registry-web がセットで起動できました。
あ、ウェブ UI 側は http://registry.running-dog.net:8080/ でアクセスできます。こちらのプロトコルは HTTP です;-)。

 
では、どうして今回、ウェブ UI は『どうして表示できないのだ?!』と、悩んでいたのが解決できたか?
についてですが『そもそも https でアクセス行ってないからじゃね?』と、思ったから。が、ベースとなっていますが、 Docker イメージである registry:2 も ekazakov/docker-registry-frontend:latest も、 docker exec で中に入ることができないんですねぇ・・。コンテナに与える環境変数は他にはないのか?確認する手段が無かった。と、いうのが大きな点ではありますが、ところがそうではないっ!!

$ docker ps -a
CONTAINER ID   IMAGE                                      COMMAND                  CREATED        STATUS        PORTS                                            NAMES
2f3a138f1b8e   ekazakov/docker-registry-frontend:latest   "/bin/sh -c $START_S…"   23 hours ago   Up 23 hours   443/tcp, 0.0.0.0:8080->80/tcp, :::8080->80/tcp   registry-web
d1e9dbf6e9a5   registry:2                                 "/entrypoint.sh /etc…"   24 hours ago   Up 24 hours   0.0.0.0:5000->5000/tcp                           registry-server
$ docker exec -it d1e9dbf6e9a5 /bin/bash
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "/bin/bash": stat /bin/bash: no such file or directory: unknown
$ docker exec -it d1e9dbf6e9a5 /bin/sh
/ # ls -l /bin/busybox 
-rwxr-xr-x    1 root     root        841288 Nov 12 11:37 /bin/busybox
/ # exit
$

 
docker ps してから docker exec -it で registry:2 に /bin/bash で入ろうしたけど、/bin/bash がないので、試しに /bin/sh にしてみたらあらは入れた。ついでに registry:2 は busybox で動作しているのねぇ。 i386 i686 系の busybox って、初めて見た。みたいな。

 
konradkleine/docker-registry-frontend:v2 も /bin/bash はないけど /bin/sh で中に入れます。
ekazakov/docker-registry-frontend:latest は /bin/bash で中に入れました。

$ docker exec -it 2f3a138f1b8e /bin/bash
root@2f3a138f1b8e:/# env
HOSTNAME=2f3a138f1b8e
APACHE_RUN_USER=www-data
TERM=xterm
ENV_DOCKER_REGISTRY_PORT=5000
APACHE_LOG_DIR=/var/log/apache2
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
APACHE_RUN_GROUP=www-data
ENV_DOCKER_REGISTRY_USE_SSL=1
SOURCE_DIR=/tmp/source
WWW_DIR=/var/www/html
SHLVL=1
HOME=/root
START_SCRIPT=/root/start-apache.sh
ENV_DOCKER_REGISTRY_HOST=registry.running-dog.net
_=/usr/bin/env
root@2f3a138f1b8e:/# cat /root/start-apache.sh
<略>
root@2f3a138f1b8e:/# exit
$

 
こんな感じです。 ekazakov/docker-registry-frontend:latest の ウェブ UI は apache で起動しているみたいです。 /root/start-apache.sh の中に docker run 時に指定した環境変数を取り込んでホスト名・ポート番号・プロトコルが設定されます。
この /root/start-apache.sh のファイルの中をじっくりと確認することによって、そこから想像する分には『https://でアクセスするようにしないとアカンのねえ・・。』と、思いつくのでありました。
あとは環境変数を見つけてそれをコンテナに渡してあげれば・・。ふぅ。なんとか動き出した。と、いう状態なのでありました。それが 、 DOCKER_REGISTRY_SCHEME と ENV_DOCKER_REGISTRY_USE_SSL なのでありますね。

 
それにしても、有名どころの git で拾ってきた docker イメージも docker exec で /bin/bash で中に入れないとき、 /bin/sh とかだと入れるとか、他にもっと実は色々な入り方 (裏技) があるのかもー。と、関心させられた事象だったのであります。

そして、Port:5000 番でアクセスする registry-server と、Port:8080 でアクセスする registry-web 。ふぅ。なんとか構築することができたのであります。

 
今の docker pull/push は SSL が基本です。http でアクセスできていた古いインターネット上の記事には惑わされないようにしてください;-P。

 コメントを書いてください。

HTML タグが利用できます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(必須項目)

(必須項目)

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください