2017-09-20 5 views
1

2つのDockerイメージが全く同じファイルシステム構造を持ち、対応するファイルの内容がファイルのタイムスタンプに関係なく同じであることを確認するにはどうすればよいですか?2つのDockerイメージの内容がまったく同じかどうかを確認するにはどうすればいいですか?

私は画像IDを試しましたが、同じDockerfileときれいなローカルリポジトリからビルドするときに違いがあります。このテストは、1つのイメージを作成し、ローカルリポジトリをクリーニングし、ファイルの1つに触れてその変更日を変更し、第2の画像を構築し、それらの画像IDが一致しない。私はドッカー17.06(私が信じる最新のバージョン)を使用しました。

その後、おかげ

答えて

2

いくつかの研究の後、私はテストごとに高速かつきれいな解決策を考え出しました。

総合的なソリューションはこれです:

  1. は、アーカイブディレクトリ名、シンボリックリンク名docker export ...
  2. パイプを経由してtarアーカイブにdocker create ...
  3. 輸出を経由してそのファイルシステム全体をイメージするためのコンテナを作成し、 (例えば、MD5)
  4. 異なるイメージのハッシュを比較して、内容が等しいかどうかを確認する

これだけです。

次のように技術的には、これを行うことができます。

1)例えば、ファイルmd5dockerを作成し、それを実行権限を与えます、chmod +x md5docker

#!/bin/sh 
dir=$(dirname "$0") 
docker create $1 | { read cid; docker export $cid | $dir/tarcat | md5; docker rm $cid > /dev/null; } 

2)は、ファイルtarcatを作成し、それを実行権を与え、例えば、chmod +x tarcat

#!/usr/bin/env python3 
# coding=utf-8 

if __name__ == '__main__': 
    import sys 
    import tarfile 
    with tarfile.open(fileobj=sys.stdin.buffer, mode="r|*") as tar: 
     for tarinfo in tar: 
      if tarinfo.isfile(): 
       print(tarinfo.name, flush=True) 
       with tar.extractfile(tarinfo) as file: 
        sys.stdout.buffer.write(file.read()) 
      elif tarinfo.isdir(): 
       print(tarinfo.name, flush=True) 
      elif tarinfo.issym() or tarinfo.islnk(): 
       print(tarinfo.name, flush=True) 
       print(tarinfo.linkname, flush=True) 
      else: 
       print("\33[0;31mIGNORING:\33[0m ", tarinfo.name, file=sys.stderr) 

3)今計算するために、<image>があなたのイメージの名前またはIDです./md5docker <image>を呼び出しますイメージのファイルシステム全体のMD5ハッシュ。

2つの画像の内容が同じかどうかを確認するには、手順3)で計算したハッシュ値と等しいかどうかを確認します。

このソリューションでは、コンテンツのディレクトリ構造、通常のファイルの内容、およびシンボリックリンク(ソフトとハード)のみを考慮しています。より多くの情報が必要な場合は、追加するコンテンツをテストするためにelif句を追加して(Python's tarfileを参照して、必要なコンテンツに対応するメソッドTarInfo.isXXX()を探して)tarcatスクリプトを変更するだけです。

私がこのソリューションで見る唯一の制限はPythonへの依存です(私はPython3を使用していますが、Python2に適応するのは非常に簡単です)。どのような依存関係も持た​​ない方がよい、おそらくもっと早い(おそらくこれは既に非常に高速です)。tarcatスクリプトを静的リンクをサポートする言語で記述して、スタンドアロンの実行可能ファイル(つまり、しかし、唯一のOS)。私はこれをC、Rust、OCaml、Haskellの将来の演習として残しておきます。

MD5がニーズに合わない場合は、最初のスクリプト内のmd5をハッシュユーティリティで置き換えてください。

これは誰でも読むのに役立ちます。

0

あなたは画像の内容を比較したい場合は、全ての層が同一である場合、あなたがdocker inspect <imageName>コマンドを使用することができますし、セクションのrootfsの

docker inspect redis

"RootFS": { 
     "Type": "layers", 
     "Layers": [ 
      "sha256:eda7136a91b7b4ba57aee64509b42bda59e630afcb2b63482d1b3341bf6e2bbb", 
      "sha256:c4c228cb4e20c84a0e268dda4ba36eea3c3b1e34c239126b6ee63de430720635", 
      "sha256:e7ec07c2297f9507eeaccc02b0148dae0a3a473adec4ab8ec1cbaacde62928d9", 
      "sha256:38e87cc81b6bed0c57f650d88ed8939aa71140b289a183ae158f1fa8e0de3ca8", 
      "sha256:d0f537e75fa6bdad0df5f844c7854dc8f6631ff292eb53dc41e897bc453c3f11", 
      "sha256:28caa9731d5da4265bad76fc67e6be12dfb2f5598c95a0c0d284a9a2443932bc" 
     ] 
    } 

で見ることができる画像は、同一含まれてい内容

+0

これは機能しません。私は、同じ名前の2つのイメージのビルドの間に1つのファイルをタッチし、異なるsha256を取得しました。 – mljrg

+0

あなたがファイルに触れた場合、これは異なるハッシュにつながる変更につながります。@@@@ – Marged

1

これを行うための標準的な方法はないようです。私が考えることができる最善の方法は、Dockerの多段ビルド機能を使用することです。 たとえば、ここではaplineとdebianのイメージを比較しています。あなたの場合、イメージ名を比較したいものに設定してください。

私は基本的に、各イメージのすべてのファイルをgitリポジトリにコピーし、コピーごとにコミットします。

FROM alpine as image1 

FROM debian as image2 

FROM ubuntu 
RUN apt-get update && apt-get install -y git 
RUN git config --global user.email "[email protected]" &&\ 
git config --global user.name "Your Name" 

RUN mkdir images 
WORKDIR images 
RUN git init 

COPY --from=image1/. 
RUN git add . && git commit -m "image1" 

COPY --from=image2/. 
RUN git add . && git commit -m "image2" 

CMD tail > /dev/null 

これは、2つの画像の違いを記録するgitリポジトリを持つ画像を提供します。

今、あなたは git logを行う場合は、ログを見ることができますし、 git diff <commit1> <commit2>

注意を使用して2つのコミットを比較することができ

docker build -t compare . 
docker run -it compare bash 

:画像建物は二コミットに失敗した場合、これはイメージが同一であることを意味しますコミットする変更がなければgit commitは失敗するからです。

+0

これはコメントセクションに移動します –

+0

なぜあなたはcontainer-diffソリューションを削除しましたか?それは動作しませんか? – mljrg

+0

@mljrg私が以前に試したことのない何か、それがうまくいくかどうかはわかりません。 – yamenk

関連する問題