昨日書いた記事(docker image rebase作業記録)で使っていたdocker image rebaseがobsoleteになってたので、それが取り込まれたというgo-containerregistryを調査することにしました。この中で、rebaseが実際に出来るのは、crane rebaseみたいなので、今回はそれを試してみる。
go-containerregistryとは1
googleが作成したコンテナレジストリをいじるためのライブラリ(ツールも付属してた)。元はcontainerregistryというpythonのツール。今回はこの中から、gitのrebaseの感覚で、dockerのimageをrebase(実際にはlayerの置き換え)してくれるcrane rebaseを使用する。
動機
例えばapacheのイメージを目的別に何個も作成したいとき、ベースとなるイメージを元に、その派生物として目的別のイメージを作成すると、レイヤが使い回されて容量が減ると思う。しかし、その後パッケージが古くなってaptやyumなどでそれぞれのイメージを更新すると、目的別のイメージの数分同じようなレイヤが作成されてしまう。
これを、ベースとなるイメージの更新だけで済ませられないか?つまり、rebaseできないか?ということで調べてみた。
作業環境
- VirtualBox上のUbuntu 18.10
- Docker 18.09
- Docker Registry 17.09(TLSあり&Basic認証でDocker Clientはlogin済)
※Registryがないとrebaseできません
作業概要
元のツール(docker image rebase)には超分かりやすい絵がついていたが、obsoleteになった瞬間readmeからその絵も消えてしまい、新しいツール(crane rebase)には絵がなかったので、こちらにリンクを載せておく。
こういうことをしたいので、パラメータに必要なイメージと以下の手順で作成し、rebaseする。
- privateなDocker Registryにdebianイメージをpush(originalとしてタグ付け)
- originalからコンテナを起動して、終了してcommit/push(v1_baseとしてタグ付け)
- v1_baseからコンテナを起動し、コンテナの中に/home/test/touchという空ファイルを作成して終了してcommit/push(v1としてタグ付け)
- originalからコンテナを起動し、xxxをインストールして終了してcommit/push(v2_baseとしてタグ付け)
- crane rebaseを使用して、v1_base,v1,v2_baseから、v2としてタグ付けされるイメージを作成する
- 確認
作業内容
(1)Docker Registryにdebianイメージをpush(original)
Docker Hubからdebian:latestをpull
$ docker pull debian
Docker Registry(便宜上example.comとする)上のイメージ(my-debian:original)としてタグ付けしてpush
$ docker tag debian example.com/my-debian:original
$ docker push example.com/my-debian:original
(2)originalからコンテナを起動して、終了してcommit/push(v1_base)
$ docker run -it --name my-debian example.com/my-debian:original
# exit
$ docker commit my-debian example.com/my-debian:v1_base
$ docker push example.com/my-debian:v1_base
$ docker container rm -v my-debian
(3)v1_baseに/home/test/touchという空ファイルを作成してcommit/push(v1)
$ docker run -it --name my-debian example.com/my-debian:v1_base
# mkdir /home/test
# touch /home/test/touch
# exit
$ docker commit my-debian example.com/my-debian:v1
$ docker push example.com/my-debian:v1
$ docker container rm -v my-debian
(4)v1_baseにslをインストールしてcommit/push(v2_base)
$ docker run -it --name my-debian example.com/my-debian:original
# apt update
# apt upgrade
# apt install sl
# /usr/games/sl
# exit
$ docker commit my-debian example.com/my-debian:v2_base
$ docker push example.com/my-debian:v2_base
$ docker container rm -v my-debian
(5)crane rebaseを使用して、v2作成
(5)-1. golangインストール
$ sudo apt install golang-go
(5)-2. craneインストール
$ go get -u github.com/google/go-containerregistry/cmd/crane
※以降では環境変数などが未設定で、$HOME/go/
にインストールされていると仮定
(5)-3. 自己証明書の配置(必要であれば)
今回docker registryで用意したのは自己証明書なので、証明書を/etc/docker/certs.d/*辺りに入れてあった。
しかし、ここを見るのはdockerだけなので、Ubuntuの一般的な証明書登録手順2を踏む。
$ sudo mkdir /usr/local/share/ca-certificates/self
$ sudo cp example.com.crt /usr/local/share/ca-certificates/self/
$ sudo update-ca-certificates
※selfは何でもいい
(5)-4. crane rebase実行
$ ~/go/bin/crane rebase \
--original=example.com/my-debian:v1 \
--old_base=example.com/my-debian:v1_base \
--new_base=example.com/my-debian:v2_base \
--rebased=example.com/my-debian:v2
(6)確認
$ docker run -it --name my-debian example.com/my-debian:v2
# ls -lAF /home/test # v1でのコミットの反映を確認
# /usr/games/sl # v2_baseでのコミットの反映を確認
# exit
$ docker container rm -v my-debian
/home/test/touchの存在が確認でき、slが動けば成功。
→成功
結論
google様万歳
[^docker image rebase]: docker image rebase