ウェブで色々調べてみると、みんな中途半端なネタしかなくて、ウェブ 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 サーバ本体です。
二番目の docker pull は ウェブで検索すると良く出てくる Registry のウェブ UI です。
三番目の docker pull は registry:2 のウェブ 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/
# cat cert.pem > /opt/docker/repository/certs/domain.crt
# cat chain.pem > /opt/docker/repository/certs/ca.crt
# cat 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(^^;;。
そして、追加でもう少し。
# cd /usr/local/etc/letsencrypt/live/running-dog.net/
# cat cert.pem > /etc/pki/tls/certs/running-dog.net.crt
# update-ca-trust
# systemctl restart docker
|
証明書を準備したら上記コマンドを実行してください。証明書を更新したときも実行してください。
SSL 証明書を /etc/pki/tls/certs/ に設置したあと update-ca-trust コマンドを叩いて dockerd を再起動しなます。
これをやらないと docker pull や push がエラーになるかもしれません。
さてと。これで SSL 証明書関連の準備が完了です。起動するときは以下のような感じ。
# 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 で) アクセスすると開いているかと思います。
Registry サーバは 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 サーバ側の設定と起動方法になります。ウェブ UI がなくても上記 curl でイメージとタグ番号の確認はできます。
では、ここからはいよいよウェブ UI 側のコンテナの起動です。
インターネット上で検索してみると、docker run してサクっと Registry サーバに接続してその情報を表示してくれる。みたいなサイトがゴマンとありますが、あれ、みんなウソです。全然表示してくれない。なんでやねんっ!?
僕もずいぶんと悩みました。どんなにやってもウェブ UI のコンテナから Registry サーバにアクセスできないっ!! ずっと悩んでいたのですが、ようやっと、問題解決です。
先にタネ明かししますが Registry サーバへは 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 サーバ の情報を表示できなかったんですね。
ここの情報について書いているサイト、ほぼ皆無です。
ウェブ 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 image を利用してみました。
-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 サーバに https でアクセスしに行って、ウェブ UI 上に登録されている情報を表示してくれるようになります。
いやぁ・・。疲れた。あとはひたすらウェブ UI を使い込んでいくことなるかと思います。ふぅ・・。
と、いうことで、 https でアクセスする Registry サーバと Registry サーバから https で情報を取りに行ってウェブ UI に表示してくれる Registry サーバのウェブ UI がセットで起動できました。
あ、ウェブ UI 側は http://registry.running-dog.net:8080/ でアクセスできます。こちらのプロトコルは http です;-)。
では、どうして今回、ウェブ UI は『どうして表示できないのだ?!』と、悩んでいたのが解決できたか?についてですが『そもそも https でアクセス行ってないからじゃね?』と、思ったから。が、ベースとなっていますが Docker image である 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 image も docker exec で /bin/bash で中に入れないとき /bin/sh とかだと入れるとか、他にもっと実は色々な入り方 (裏技) があるのかもー。と、関心させられた事象だったのであります。
そして、Port:5000 番でアクセスする Registry サーバと、Port:8080 でアクセスする ウェブ UI 。ふぅ。なんとか構築することができたのであります。
今の docker pull/push は SSL が基本です。http でアクセスできていた古いインターネット上の記事には惑わされないようにしてください;-P。