お金をかけずにサーバーの勉強をしよう

プライベートの Dockerレジストリを作る

2022年9月18日

メニューへ戻る

Dockerを活用するにあたり、いずれは自前の Dockerイメージを作っていくことになると思います。

作るところまでは良いとして、例えばそれを開発者に配ることで各開発者が統一された開発環境で開発できる、そういう実践的な方法が流行っているようです。
(私はそういう環境を運用したことがありませんが)

この際、dockerの exportコマンドで、Dockerイメージをファイル化して、共有のファイルサーバー等に置いておくという方法もありますが、Dockerレジストリ(という Dockerイメージのデータベース)を使うと、イメージの利用者の利便性が上がります。

Dockerは Docker Hub を使えと言っていますが、サーバーエンジニアとしては Dockerレジストリってどういうものなのかを知っておいた方が良いと思いますし、そもそも Docker Hubの制限をなくすのは有償だったはずだし…。

これにはプライベートの Dockerレジストリを作って動かしてみるのが分かりやすいしタダなので、ここでは実際に作ってみようと思います。
 

前提として、Dockerがインストールされている環境が必要です。

ここでは、Ubuntu Server 22.04.1にインストールした Dokcer 20.10を使います。

Ubuntu Serverのインストールについては「Ubuntu Linux Serverをインストール」と「Ubuntu Serverの初期設定」に、
Dockerのインストールについては「Dockerエンジン インストール」に、それぞれ書いています。


Dockerレジストリもまた Dockerのコンテナとして動きます。

Dockerのドキュメントに作成手順がありますので、それに従って作ります。
Docker レジストリ TL;DR


では早速。
手順に従い Dockerレジストリのコンテナをダウンロードして実行します。

subro@UbuntuServer2204:~$ docker run -d -p 5000:5000 --name registry registry:2
Unable to find image 'registry:2' locally
2: Pulling from library/registry
213ec9aee27d: Pull complete
5299e6f78605: Pull complete
4c2fb79b7ce6: Pull complete
74a97d2d84d9: Pull complete
44c4c74a95e4: Pull complete
Digest: sha256:83bb78d7b28f1ac99c68133af32c93e9a1c149bcd3cb6e683a3ee56e312f1c96
Status: Downloaded newer image for registry:2
bf15a10473c2db66b0704ac26b4d27d3523f16cbc93119498a0bd163652ddc87

動き出しました。
5000/tcpで待ち受けているようです。


これでプライベートレジストリの作成は終了で、手順ではこのあと ubuntu のイメージをダウンロードして、それをそのまま今作ったレジストリに入れていますが、ここで一つ考慮したいことがあります。

Dockerレジストリは手間をかけて作成したコンテナイメージの容れモノであると考えると、やはりバックアップが重要になると思います。

常に障害の事、バックアップの事が機能より先に思い浮かぶのは… 運用者の性…。


コンテナ内部のストレージに保存されているファイルのバックアップの方法は色々と考えられますが、やはりコンテナイメージファイルの置き場はコンテナ外部に設定して、(ホスト)OS側でコピー(バックアップ)を作るのがシンプルで良い気がします。

Dockerの永続ストレージ使用の方法には、bindと volumeがありますが、OS側でコピーしたり戻したりすることを鑑みて、bindでやってみます。


上で作ったコンテナを一旦削除して、永続ストレージをくっつけた形で作り直してみます。
先に永続ストレージとなるディレクトリを作っておきましょう。

subro@UbuntuServer2204:~$ sudo mkdir /docker_registry

subro@UbuntuServer2204:~$ ls -ld /docker_registry
drwxr-xr-x 2 root root 4096  9月 18 08:03 /docker_registry

稼働中のコンテナを停止します。
(何を指定しているか明確にするためコンテナIDを使っています)

subro@UbuntuServer2204:~$ docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED          STATUS          PORTS                                       NAMES
bf15a10473c2   registry:2   "/entrypoint.sh /etc…"   24 seconds ago   Up 23 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry

subro@UbuntuServer2204:~$ docker stop bf15a10473c2
bf15a10473c2

停止したコンテナを削除します。

subro@UbuntuServer2204:~$ docker rm bf15a10473c2
bf15a10473c2

永続ストレージを付けた形で起動します。
Dockerレジストリがコンテナ内部で使うディレクトリが /var/lib/registry です。

subro@UbuntuServer2204:~$ docker run -d -p 5000:5000 -v /docker_registry:/var/lib/registry --name registry registry:2
208ed897332f2ec1bc44112285785db8e475f5588a4bb75d483735fd8d345583

立ち上がりました。

Dockerレジストリの WebAPIでレジストリに登録されているコンテナの一覧を見てみます。
(JSON形式の結果はパイプで jqコマンド(Command-line JSON processor)に渡して見やすく整形しています)

subro@UbuntuServer2204:~$ curl -s http://localhost:5000/v2/_catalog | jq
{
  "repositories": []
}

空ですね。当たり前ですが。


さて、これでプライベートの Dockerレジストリはできたはずなので、何か入れたい…。

丁度「開発用の Dockerコンテナを作る」で作った Denoの開発用コンテナイメージがあるので、それを入れます。

subro@UbuntuServer2204:~$ docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
ubuntu-deno   latest    54da0e74a1a6   16 hours ago   332MB
registry      2         3a0f7b0a13ef   5 weeks ago    24.1MB

コンテナイメージをプライベートレジストリにプッシュします。

コンテナイメージID「54da0e74a1a6」をプライベートレジストリ内では「ubuntu_deno:version1.0」という名前になるよう紐付けます。
Dockerのドキュメントではこの箇所です。
プライベートリポジトリ内のイメージタグづけ

subro@UbuntuServer2204:~$ docker tag 54da0e74a1a6 localhost:5000/ubuntu_deno:version1.0

紐付けられた結果です。

subro@UbuntuServer2204:~$ docker images
REPOSITORY                   TAG          IMAGE ID       CREATED        SIZE
ubuntu-deno                  latest       54da0e74a1a6   17 hours ago   332MB
localhost:5000/ubuntu_deno  version1.0  54da0e74a1a6   17 hours ago  332MB
registry                     2            3a0f7b0a13ef   5 weeks ago    24.1MB

紐付けられたコンテナイメージをプライベートレジストリにプッシュします。

subro@UbuntuServer2204:~$ docker push localhost:5000/ubuntu_deno:version1.0
The push refers to repository [localhost:5000/ubuntu_deno]
1d2b55e15537: Pushed
7f5cbd8cc787: Pushed
version1.0: digest: sha256:0b40f0e0d2b42231118239a0abeea1d6b944a9c7b44a06bc1769e9757a50dfd7 size: 742

プッシュできました。

改めてプライベートレジストリの中身を WebAPIで見てみましょう。

subro@UbuntuServer2204:~$ curl -s http://localhost:5000/v2/_catalog | jq
{
  "repositories": [
    "ubuntu_deno"
  ]
}

登録されました。

永続ストレージ用に作ったディレクトリ下もディレクトリやファイルが増えました。

subro@UbuntuServer2204:/docker_registry$ ls -lR
.:
合計 4
drwxr-xr-x 3 root root 4096  9月 18 09:28 docker

./docker:
合計 4
drwxr-xr-x 3 root root 4096  9月 18 09:28 registry

./docker/registry:
合計 4
drwxr-xr-x 4 root root 4096  9月 18 09:28 v2

〜〜〜 以下略 〜〜〜


登録されたイメージをちゃんと取れるか、他のノードにある Dockerを使ってプルしてみます。
CentOS8の仮想マシンがあったのでそれを使いました。

Dockerはコンテナイメージをプルする時 HTTPSを使うんですが、今回作ったプライベートレジストリは内部用と思ってセキュアじゃない(HTTP)ので、普通にプルするとエラーになります。

CentOS8の Docker設定ファイル [/etc/docker/daemon.json] に「このレジストリはセキュアじゃなくてもOKです」という記述を追加してやります。

[subro@CentOS8 ~]$ cat /etc/docker/daemon.json
{ "insecure-registries":["UbuntuServer2204:5000"] }

この後、CentOS8では Dockerエンジンの再起動を行いました。

[subro@CentOS8 ~]$ sudo systemctl daemon-reload

[subro@CentOS8 ~]$ sudo systemctl restart docker

コンテナイメージをプルします。
(このOSではユーザーを dockerグループに入れていないので sudoを使っています)

[subro@CentOS8 ~]$ sudo docker pull UbuntuServer2204:5000/ubuntu_deno:version1.0
version1.0: Pulling from ubuntu_deno
2b55860d4c66: Pull complete
03e79f3179bb: Pull complete
Digest: sha256:0b40f0e0d2b42231118239a0abeea1d6b944a9c7b44a06bc1769e9757a50dfd7
Status: Downloaded newer image for UbuntuServer2204:5000/ubuntu_deno:version1.0
UbuntuServer2204:5000/ubuntu_deno:version1.0

プルできました。

確認してみます。

[subro@CentOS8 ~]$ sudo docker images
REPOSITORY                          TAG          IMAGE ID       CREATED         SIZE
UbuntuServer2204:5000/ubuntu_deno   version1.0   54da0e74a1a6   18 hours ago    332MB

ちゃんとプルできていました。


これでプライベートレジストリとしての動作は良好のようです。

あとは永続ストレージのディレクトリを cronか何かで定期的にどこぞにバックアップしておけば運用としてはとりあえず OKかと思います。

それから永続ストレージのディレクトリは RAIDにしておいた方が良いと思います。
Ubuntu Server 22.04.1でデフォルトで使える LVM2の機能で RAIDを作る話を「LVM2でソフトウェアRAID構築」に書いてありますので、良ければどうぞ。


作り始めた時は難しいかと思っていましたが、実は大変に簡単なのでした。

チームに対して Dockerを使った開発環境を配布するなら、プライベートレジストリの作成はお勧めですね。

(使ったことないけど)Docker Desktopでもレジストリからの取得の方が楽そうですものね。