原文はこちら。
https://blogs.oracle.com/gman/creating-a-local-docker-registry
この数ヶ月、サービス実行のためのインフラストラクチャを立ち上げる仕事をしています。ほとんどの場合、Oracle SolarisのIPSリポジトリとAutomated Installerのネットワークブートサービスが有効でいい感じでしたし、Oracle Linux上でローカルのDockerレジストリを立ち上げたので、私の経験を共有します。
残念ながら、ローカルレジストリの複製のための、Dockerレジストリ関連の素敵なツールに遭遇したことがありませんでした。そのため、Docker Registry HTTP v2 APIと単純なPythonスクリプティングにちょっと依存した独自のツールを書くことにしました。
Docker Registry HTTP API V2
https://docs.docker.com/registry/spec/api/
今回のユースケースは、特定のタグを持つすべてのイメージを取得し、ローカルのDockerレジストリを作成する、というものです。以下に手順の概要を示します。
1. Install Docker engine
非常に簡単です。yumコマンドを使って、docker-engineをインストールします。
yum install docker-engine
今回はPythonで書いたので、単純なcheck_callで十分でしたが、プライベートCLI APIを使うことにしたため、すぐに次のスニペットを使うことができました。
ybc = cli.YumBaseCli()
ybc.conf.assumeyes = True
ybc.conf.downloadonly = False
ybc.installPkgs(packages)
ybc.buildTransaction()
ybc.doTransaction()
2. Configure Docker to pull from an internal registry over HTTP
内部DockerレジストリからPullしていたので、Dockerサービスを有効化する前にセキュアでないレジストリを追加する必要がありました。この作業は
/etc/sysconfig/docker
に以下を追加することで対処できます。
INSECURE_REGISTRY="--insecure-registry internal-docker-reg.us.oracle.com:5000"
3. Enable the Docker service
Dockerサービスの有効化、および開始は、以下のコマンドを使います。
systemctl enable docker
systemctl start docker
4. Get a list of images using REST
特定のタグのイメージをPullしたかったのですが、Dockerには'latest'タグという概念があります。これは直近にパブリッシュされたイメージという意味で、残念ながら、最新のバージョンであるとは限りません。そのため、一貫性の観点でこの厄介なことを避けることにしました。以下のPythonのコードを使い、簡単なWebリクエストで、レジストリのリポジトリに含まれる全てのイメージ(特にイメージのグループ)のリストを取得できます。
docker_url = "http://internal-docker-reg.us.oracle.com:5000/v2/_catalog"
r = requests.get(docker_url, verify=False)
json_data = r.json()
そこからレスポンスを解析し、Dockerイメージのリストを取得できます。以下のような形式で取得します(私の場合、OpenStackベースのDockerイメージ)。
{u'repositories': [u'openstack/ol-openstack-aodh-api', u'openstack/ol-openstack-aodh-base', ... ]}
この結果は簡単にパースできます。
for c in json_data['repositories']:
print("Image: %s" % c)
5. Get a list of tags for an image using REST
イメージ名が分かれば、各イメージのタグの一覧を再帰的に取得できます。以下のスニペットはPythonで記述した例です。
docker_image_tag_url = "http://internal-docker-reg.us.oracle.com:5000/v2" + image_name + "/tags/list"
r = requests.get(docker_image_tag_url, verify=False)
image_tags = r.json()
以下のような結果になるでしょう。
{u'name': u'openstack/ol-openstack-aodh-api', u'tags': [u'3.0.1.latest', u'3.0.1.90', ... ]}
再度申し上げますが、パースは非常に簡単です。
6. Pull the image to local registry
続いて、関心のあるタグに基づいてイメージをPull Downします。
docker pull http://internal-docker-reg.us.oracle.com:5000/v2/openstack/ol-openstack-aodh-api:3.0.1.153
docker save
コマンドを使い、tarballの形式でイメージのローカルコピーも作成しました。
docker save internal-docker-reg.us.oracle.com:5000/openstack/ol-openstack-aodh-api:3.0.1.153 | gzip -c > openstack/ol-openstack-aodh-api.tar.gz
7. Running a Docker registry instance
お持ちのDockerイメージを外部アクセス可能にしたい場合、
docker.io
からレジストリのDockerイメージをPullし、実行する必要もあります。
docker pull registry:2
docker run -d -p 5000:5000 --restart=always --name=registry registry:2
docker ps
commandコマンドを使うと実行中のDockerコンテナがあることがわかります。
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3e03011bb4a5 registry:2 "/entrypoint.sh /etc/" 5 weeks ago Up 5 weeks 0.0.0.0:5000->5000/tcp registry
8. Republish your Docker images
最後に、ローカルレジストリ中のイメージにタグを付け、レジストリに入れる必要がありますが、この手順ではイメージIDが必要なので、以下のコマンドでイメージIDを取得しました。
docker images --format="{{.ID}},{{.Repository}}"
この結果、以下のような簡単にパースできるデータが出てきます。
5d289275c280,ca-openstack-docker-reg.us.oracle.com:5000/openstack/ol-openstack-neutron-base
393d7c702a00,ca-openstack-docker-reg.us.oracle.com:5000/openstack/ol-openstack-ironic-base
cc52d8d76395,ca-openstack-docker-reg.us.oracle.com:5000/openstack/ol-openstack-ceilometer-base
...
この後、イメージにタグを付け、レジストリ・インスタンスにPushすることができます。
docker tag 5d289275c280 http://mynewhost.us.oracle.com:5000/openstack/ol-openstack-neutron-base:3.0.1.153
docker push http://mynewhost.us.oracle.com:5000/openstack/ol-openstack-neutron-base:3.0.1.153
そして、単純なforループですべてのイメージをPythonで大規模に処理しました。
最終的に以下のようなリストになります。
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mynewhost.us.oracle.com:5000/openstack/ol-openstack-neutron-base 3.0.1.113 751f286bc25e 4 months ago 958 MB
...
この段階に到達すると、この新しいホスト mynewhost.us.oracle.com にすべてのDockerイメージが再公開されます。これはつまり、他のクライアントが私の内部サーバーから簡単にpullできるということです。