proxy環境下でDocker Registryの構築

自分たちで開発した Docker コンテナをイントラネット内で使ってもらうために、Docker Registry を構築しました。構築時、proxyでハマったので簡単に手順を残します。
OS は CentOS7.7 を使用します。この構築手順は OS のインストール直後を想定しています。また、証明書や認証の設定については、省略させていただきます。

# Docker Registry とは

社内のみで Docker イメージを登録、取得したいケースがあります。このような場合、Dockerイメージが大量に保存されている Docker Hub を利用するのではなく、社内用のDockerイメージの保管庫が必要になります。Docker Registry は、Docker イメージを保存しておいて、提供するサービスです。Docker Registry を 利用することで、社内で Docker イメージの登録（docker push）、取得（docker pull）が可能になります。
Docker Registry も Docker イメージとして、Docker Hub に登録されていて、取得（docker pull）して、それを使ってコンテナを起動させることで、Docker Registry を構築することができます。

詳細は公式サイト [Docker Registry](https://docs.docker.com/registry/) で紹介しています。

# Docker のインストール

Docker Registry をインストールする前に、まず、Docker をインストールします。

## 各種設定

yum に proxy の設定を追加するために /etc/yum.conf を編集します。

```
$ sudo vi /etc/yum.conf
```
以下を yum.conf に追加します。proxy の利用に認証が必要な場合、proxy_username, proxy_passwird も追加して下さい。今回は省略します。

```/etc/yum.conf
proxy=http://<proxy_host>:<proxy_port>
```
デフォルトのリポジトリ設定では、yum 実行時にタイムアウトになる可能性がありますので、/etc/yum.repos.d/CentOS-Base.repo を編集します。

```
$ sudo vi /etc/yum.repos.d/CentOS-Base.repo
```

[base], [update], [extras], [centosplus] の baseurl を以下のように置き換えます。

```/etc/yum.repos.d/CentOS-Base.repo
[base]
baseurl=http://ftp.riken.jp/Linux/centos/$releasever/os/$basearch/
[updates]
baseurl=http://ftp.riken.jp/Linux/centos/$releasever/updates/$basearch/
[extras]
baseurl=http://ftp.riken.jp/Linux/centos/$releasever/extras/$basearch/
[centosplus]
baseurl=http://ftp.riken.jp/Linux/centos/$releasever/centosplus/$basearch/
```

yum update を実行して、各パッケージを最新にします。
```
$ sudo yum update
```

## Docker のインストール

公式な手順 [Get Docker Engine - Community for CentOS](https://docs.docker.com/install/linux/docker-ce/centos/) に従って、以下のようにDockerのインストールを進めます。

古いバージョンの Docker パッケージをアンインストールします。

```
$ sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
```

Docker のインストールに必要な yum-utils, device-mapper-persistent-data, lvm2 パッケージをインストールします。

```
$ sudo yum install -y yum-utils device-mapper-persistent-data lvm2
```

Docker インストール用リポジトリを yum に追加します。

```
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
```

リポジトリーの構成を表示して、docker-ce-stable が含まれていれば問題ありません。

```
$ sudo yum repolist
読み込んだプラグイン:fastestmirror, langpacks
Loading mirror speeds from cached hostfile
repo ID                         repo name                         status
base/7/x86_64                   CentOS-7 - Base                   10,097
docker-ce-stable/x86_64         Docker CE Stable - x86_64             61
extras/7/x86_64                 CentOS-7 - Extras                    305
updates/7/x86_64                CentOS-7 - Updates                   711
```

Docker をインストールします。

```
$ sudo yum install docker-ce docker-ce-cli containerd.io
```

`docker -v` で Docker がインストールされたか確認できます。

```
$ sudo docker -v
Docker version 19.03.4, build 9013bf583a
```

Docker を起動します。

```
$ sudo systemctl start docker
```

以下で Docker の起動を確認します。エラーが出力されなければ、Docker は起動されています。

```
$ sudo docker search hello-world
```


## Docker の設定

sudo を使用しなくても Docker が使用できるように、現在のユーザーを docker グループに追加します（docker グループは、Docker インストール後、追加されている）。

```
$ sudo usermod -aG docker $USER
```

docker のプロキシを設定します。詳細は公式サイトの [Control Docker with systemd](https://docs.docker.com/config/daemon/systemd/) に記述されています。

```
$ sudo mkdir -p /etc/systemd/system/docker.service.d
$ sudo vi /etc/systemd/system/docker.service.d/http-proxy.conf
```

以下のように、http-proxy.conf に proxy の情報を記述します。

```/etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://<proxy_host>:<proxy_port>" "HTTPS_PROXY=http://<proxy_host>:<proxy_port>" "NO_PROXY=localhost,127.0.0.1"
```

設定を反映して、Docker を再起動します。

```
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
```

`docker info` で proxy が設定されたか確認ができます。最後の方で以下のように表示されます。

```
$ docker info
 HTTP Proxy: http://<proxy_host>:<proxy_port>
 HTTPS Proxy: http://<proxy_host>:<proxy_port>
 No Proxy: localhost, 127.0.0.1
```

以下で、OS 起動時に Docker を自動起動にします。詳細は公式サイトの [Configure Docker to start on boot](https://docs.docker.com/install/linux/linux-postinstall/#configure-docker-to-start-on-boot) に記述されています。

```
$ sudo systemctl enable docker
```

# Docker Registry の構築

インストールした Docker を用いて、Docker Registory を構築していきます。

## イメージの取得

はじめに、Docker Registry イメージの確認をします。

```
$ docker search registry
```

`docker pull` で Docker Registry イメージを取得します。

```
$ docker pull registry
Using default tag: latest
latest: Pulling from library/registry
c87736221ed0: Pull complete 
1cc8e0bb44df: Pull complete 
54d33bcb37f5: Pull complete 
e8afc091c171: Pull complete 
b4541f6d3db6: Pull complete 
Digest: sha256:8004747f1e8cd820a148fb7499d71a76d45ff66bac6a29129bfdbfdc0154d146
Status: Downloaded newer image for registry:latest
docker.io/library/registry:latest
```

`docker images` で registry イメージが取得できていることを確認します。

```
$ docker images
REPOSITORY          TAG       IMAGE ID         CREATED             SIZE
registry            latest    f32a97de94e1     8 months ago        25.8MB
```

## コンテナの起動

ホスト側に、push されたイメージを保存するために以下のディレクトリを作成します。

```
/root/docker/registry/
```

取得した registry イメージをもとに Docker Registry 用のコンテナを `docker run` で起動します。ポートは5000番を使用します。

```
$ docker run -d -p 5000:5000 registry
$ docker run -d -p 5000:5000 -v /root/docker/registry/data:/var/lib/registry --restart=always --name registry01 registry:latest
```

`docker ps` で Docker Registry コンテナが動作していることを確認します。

```
$ docker ps
CONTAINER ID  IMAGE            COMMAND                 CREATED        STATUS      PORTS                   NAMES
091ea25e90fe  registry:latest  "/entrypoint.sh /etc…"  8 seconds ago  Up 25 hours 0.0.0.0:5000->5000/tcp  registry01
```


# 他 Docker Client から Docker Registry コンテナにアクセス

## 各種設定

他の環境で、前述と同じように [Dockerのインストール](# Docker のインストール)を行います。

以下のように、http-proxy.conf の NO_PROXYに Docker Registry のIPアドレスまたはサーバ名を記述します。

```/etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://<proxy_host>:<proxy_port>" "HTTPS_PROXY=http://<proxy_host>:<proxy_port>" "NO_PROXY=localhost,127.0.0.1,<registry_host>"
```

## insecure registry の設定

Registry が暗号化されていないhttp通信の場合は、insecure registry にその Registry を登録しないと、Dockerイメージをpullすることができないので、設定します。

```
$ sudo vi /etc/docker/daemon.json
```

/etc/docker/daemon.json に以下を追加します。

```/etc/docker/daemon.json
{ "insecure-registries":["<registry_host>:<registry_port>"] }
```

設定を反映して、Docker を再起動します。

```
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
```

## イメージの登録

まず、 Docker Registry に登録するイメージを準備する。今回は確認のために hello-world イメージを `docker pull` します。

```
$ docker pull hello-world
```

イメージを Docker Registry に登録するために、hello-world イメージにタグを付けます。

```
$ docker tag hello-world <registry_host>:5000/hello-world
```

`docker images` で &lt;registry_host&gt;:5000/hello-world が作成されていることを確認します。

```
$ docker images 
REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
hello-world                       latest              fce289e99eb9        10 months ago       1.84kB
<registry_host>:5000/hello-world  latest              fce289e99eb9        10 months ago       1.84kB
```

`docker push` で &lt;registry_host&gt;:5000/hello-world イメージを Docker Registry に登録します。

```
$ docker push <registry_host>:5000/hello-world
The push refers to repository [<registry_host>:5000/hello-world]
af0b15c8625b: Pushed 
latest: digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a size: 524
```


## イメージの取得

Docker Registry からイメージの取得する前に、確認のため、ローカルのイメージを削除します。

```
$ docker rmi <registry_host>:5000/hello-world
```

`docker images` で &lt;registry_host&gt;:5000/hello-world が削除されていることを確認します。

```
$ docker images 
REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
hello-world                       latest              fce289e99eb9        10 months ago       1.84kB
```

`docker pull` で &lt;registry_host&gt;:5000/hello-world イメージを Docker Registry から取得します。

``` 
$ docker pull <registry_host>:5000/hello-world
Using default tag: latest
latest: Pulling from hello-world
Digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a
Status: Downloaded newer image for <registry_host>:5000/hello-world:latest
```  

`docker images` で &lt;registry_host&gt;:5000/hello-world が取得されていることを確認します。

```
$ docker images 
REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
hello-world                       latest              fce289e99eb9        10 months ago       1.84kB
<registry_host>:5000/hello-world  latest              fce289e99eb9        10 months ago       1.84kB
```

## registry のイメージ一覧の取得

以下の方法で registry のイメージ一覧を取得できます。

```
$ curl --noproxy <registry_host> http://<registry_host>:5000/v2/_catalog
{"repositories":["hello-world"]}
```

# まとめ
Docker Registry も Docker イメージとして、Docker Hub に登録されていて、取得して、それを使ってコンテナを起動させることで、Docker Registry を構築することができました。Docker Registry コンテナをイントラネット内で使用するためには、proxyの設定が不可欠です。proxy 設定と proxy を使わない設定を正しくできると動作まで辿り着けます。

もし、記述について誤りがあったり、気になることがあれば、編集リクエストやコメントでフィードバックしていただけると助かります。

# 参考
Docker 公式サイト他に以下の記事を参考にさせていただきました。

- [privateなdockerレジストリを構築する](https://qiita.com/zknzfz/items/13d5d07ab5bb0feb1fd1)
- [防火壁の中の Docker](https://qiita.com/jeffi7/items/3e40c59744b5801fd40a)
- [社内Proxyに阻まれていろいろ捗らない人のためのTips](https://qiita.com/sachioksg/items/289e40d69382b1d09811)