0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

docker image rebase作業記録

Last updated at Posted at 2019-03-11

docker image rebase[^docker image rebase]というdocker公式でない個人(?)が作成したツールの使い勝手を試した記録。

docker image rebaseとは[^docker image rebase]

docker公式でない個人(?)が作成した実験段階のツール。
gitのrebaseの感覚で、dockerのimageをrebase(実際にはlayerの置き換え)してくれる模様。
ただ、コミットが2018/2/25〜2018/4/27の2ヶ月程度しかなく、誰も本格的に使っている様子がない。
今回の調査で正常系の100%再現するバグが見つかった
→作者に問い合わせたら、obsoleteだからコッチ1ね、と言われた。(後日編集追加)

動機

例えばapacheのイメージを目的別に何個も作成したいとき、ベースとなるイメージを元に、その派生物として目的別のイメージを作成すると、レイヤが使い回されて容量が減ると思う。しかし、その後パッケージが古くなってaptやyumなどでそれぞれのイメージを更新すると、目的別のイメージの数分同じようなレイヤが作成されてしまう。

これを、ベースとなるイメージの更新だけで済ませられないか?つまり、rebaseできないか?ということで調べてみた。

作業環境

  • VirtualBox上のUbuntu 18.10
  • Docker 18.09
  • Docker Registry 17.09(TLSあり&Basic認証でDocker Clientはlogin済)

※Docker Registryがないとrebaseできません

作業概要

  1. privateなDocker Registryにdebianイメージをpush(originalとしてタグ付け)
  2. originalからコンテナを起動して、終了してcommit/push(v1_baseとしてタグ付け)
  3. v1_baseからコンテナを起動し、コンテナの中に/home/test/touchという空ファイルを作成して終了してcommit/push(v1としてタグ付け)
  4. originalからコンテナを起動し、xxxをインストールして終了してcommit/push(v2_baseとしてタグ付け)
  5. docker image rebaseを使用して、v1_base,v1,v2_baseから、v2としてタグ付けされるイメージを作成する
  6. 確認

作業内容

(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)docker image rebaseを使用して、v2作成

(5)-1. golangインストール

$ sudo apt install golang-go

(5)-2. docker image rebaseインストール

$ go get -u github.com/google/image-rebase

※以降では環境変数などが未設定で、$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. docker image rebase実行

$ ~/go/bin/image-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が動けば成功。

しかし冒頭に書いたとおり、バグのため、v1のコミットの反映を確認できなかった。
以下の修正を加えたところ、成功。

diff --git a/pkg/rebase/rebase.go b/pkg/rebase/rebase.go
index 0884ca9..975f60e 100644
--- a/pkg/rebase/rebase.go
+++ b/pkg/rebase/rebase.go
@@ -163,8 +163,8 @@ func (r Rebaser) Rebase(origStr, oldBaseStr, newBaseStr, rebasedStr string) erro
        }
        for i := range origLayers[len(oldBaseLayers):] {
                rebasedImage, err = mutate.Append(rebasedImage, mutate.Addendum{
-                       Layer:   origLayers[i],
-                       History: origConfig.History[i],
+                       Layer:   origLayers[i+len(oldBaseLayers)],
+                       History: origConfig.History[i+len(oldBaseLayers)],
                })
                if err != nil {
                        return fmt.Errorf("failed to append layer %d of original layers", i)

結論

誰も使ってないものは危ないので使用しない方がいい。
→go-containerregistry1なんてモノがあるのでそれを調べてから。(後日編集追加)
→調べたので続き(後日編集追加)

[^docker image rebase]: docker image rebase

  1. go-containerregistry 2

  2. https://askubuntu.com/questions/645818/how-to-install-certificates-for-command-line

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?