Преглед изворни кода

Compute TarSum on storage of image layer content

Now, newly created/imported layers will have the checksum of
the layer diff computed and stored in the image json file.

For now, it is not an error if the computed checksum does not
match an existing checksum, only a warning message is logged. The
eventual goal is to use the checksums in the image JSON to verify
the integrity of the layer contents when doing `docker load` or
`docker pull`, and error out if it does not match.

Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)
Josh Hawn пре 10 година
родитељ
комит
059e589c34
2 измењених фајлова са 31 додато и 4 уклоњено
  1. 1 0
      graph/service.go
  2. 30 4
      image/image.go

+ 1 - 0
graph/service.go

@@ -150,6 +150,7 @@ func (s *TagStore) CmdLookup(job *engine.Job) engine.Status {
 		out.Set("Os", image.OS)
 		out.SetInt64("Size", image.Size)
 		out.SetInt64("VirtualSize", image.GetParentsSize(0)+image.Size)
+		out.Set("Checksum", image.Checksum)
 		if _, err = out.WriteTo(job.Stdout); err != nil {
 			return job.Error(err)
 		}

+ 30 - 4
image/image.go

@@ -11,6 +11,7 @@ import (
 
 	log "github.com/Sirupsen/logrus"
 	"github.com/docker/docker/pkg/archive"
+	"github.com/docker/docker/pkg/tarsum"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/utils"
 )
@@ -32,6 +33,7 @@ type Image struct {
 	Config          *runconfig.Config `json:"config,omitempty"`
 	Architecture    string            `json:"architecture,omitempty"`
 	OS              string            `json:"os,omitempty"`
+	Checksum        string            `json:"checksum"`
 	Size            int64
 
 	graph Graph
@@ -74,19 +76,43 @@ func LoadImage(root string) (*Image, error) {
 	return img, nil
 }
 
+// StoreImage stores file system layer data for the given image to the
+// image's registered storage driver. Image metadata is stored in a file
+// at the specified root directory. This function also computes the TarSum
+// of `layerData` (currently using tarsum.dev).
 func StoreImage(img *Image, layerData archive.ArchiveReader, root string) error {
 	// Store the layer
 	var (
-		size   int64
-		err    error
-		driver = img.graph.Driver()
+		size        int64
+		err         error
+		driver      = img.graph.Driver()
+		layerTarSum tarsum.TarSum
 	)
 
 	// If layerData is not nil, unpack it into the new layer
 	if layerData != nil {
-		if size, err = driver.ApplyDiff(img.ID, img.Parent, layerData); err != nil {
+		layerDataDecompressed, err := archive.DecompressStream(layerData)
+		if err != nil {
 			return err
 		}
+
+		defer layerDataDecompressed.Close()
+
+		if layerTarSum, err = tarsum.NewTarSum(layerDataDecompressed, true, tarsum.VersionDev); err != nil {
+			return err
+		}
+
+		if size, err = driver.ApplyDiff(img.ID, img.Parent, layerTarSum); err != nil {
+			return err
+		}
+
+		checksum := layerTarSum.Sum(nil)
+
+		if img.Checksum != "" && img.Checksum != checksum {
+			log.Warn("image layer checksum mismatch: computed %q, expected %q", checksum, img.Checksum)
+		}
+
+		img.Checksum = checksum
 	}
 
 	img.Size = size