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)
| ... | ... |
@@ -150,6 +150,7 @@ func (s *TagStore) CmdLookup(job *engine.Job) engine.Status {
|
| 150 | 150 |
out.Set("Os", image.OS)
|
| 151 | 151 |
out.SetInt64("Size", image.Size)
|
| 152 | 152 |
out.SetInt64("VirtualSize", image.GetParentsSize(0)+image.Size)
|
| 153 |
+ out.Set("Checksum", image.Checksum)
|
|
| 153 | 154 |
if _, err = out.WriteTo(job.Stdout); err != nil {
|
| 154 | 155 |
return job.Error(err) |
| 155 | 156 |
} |
| ... | ... |
@@ -11,6 +11,7 @@ import ( |
| 11 | 11 |
|
| 12 | 12 |
log "github.com/Sirupsen/logrus" |
| 13 | 13 |
"github.com/docker/docker/pkg/archive" |
| 14 |
+ "github.com/docker/docker/pkg/tarsum" |
|
| 14 | 15 |
"github.com/docker/docker/runconfig" |
| 15 | 16 |
"github.com/docker/docker/utils" |
| 16 | 17 |
) |
| ... | ... |
@@ -32,6 +33,7 @@ type Image struct {
|
| 32 | 32 |
Config *runconfig.Config `json:"config,omitempty"` |
| 33 | 33 |
Architecture string `json:"architecture,omitempty"` |
| 34 | 34 |
OS string `json:"os,omitempty"` |
| 35 |
+ Checksum string `json:"checksum"` |
|
| 35 | 36 |
Size int64 |
| 36 | 37 |
|
| 37 | 38 |
graph Graph |
| ... | ... |
@@ -74,19 +76,43 @@ func LoadImage(root string) (*Image, error) {
|
| 74 | 74 |
return img, nil |
| 75 | 75 |
} |
| 76 | 76 |
|
| 77 |
+// StoreImage stores file system layer data for the given image to the |
|
| 78 |
+// image's registered storage driver. Image metadata is stored in a file |
|
| 79 |
+// at the specified root directory. This function also computes the TarSum |
|
| 80 |
+// of `layerData` (currently using tarsum.dev). |
|
| 77 | 81 |
func StoreImage(img *Image, layerData archive.ArchiveReader, root string) error {
|
| 78 | 82 |
// Store the layer |
| 79 | 83 |
var ( |
| 80 |
- size int64 |
|
| 81 |
- err error |
|
| 82 |
- driver = img.graph.Driver() |
|
| 84 |
+ size int64 |
|
| 85 |
+ err error |
|
| 86 |
+ driver = img.graph.Driver() |
|
| 87 |
+ layerTarSum tarsum.TarSum |
|
| 83 | 88 |
) |
| 84 | 89 |
|
| 85 | 90 |
// If layerData is not nil, unpack it into the new layer |
| 86 | 91 |
if layerData != nil {
|
| 87 |
- if size, err = driver.ApplyDiff(img.ID, img.Parent, layerData); err != nil {
|
|
| 92 |
+ layerDataDecompressed, err := archive.DecompressStream(layerData) |
|
| 93 |
+ if err != nil {
|
|
| 88 | 94 |
return err |
| 89 | 95 |
} |
| 96 |
+ |
|
| 97 |
+ defer layerDataDecompressed.Close() |
|
| 98 |
+ |
|
| 99 |
+ if layerTarSum, err = tarsum.NewTarSum(layerDataDecompressed, true, tarsum.VersionDev); err != nil {
|
|
| 100 |
+ return err |
|
| 101 |
+ } |
|
| 102 |
+ |
|
| 103 |
+ if size, err = driver.ApplyDiff(img.ID, img.Parent, layerTarSum); err != nil {
|
|
| 104 |
+ return err |
|
| 105 |
+ } |
|
| 106 |
+ |
|
| 107 |
+ checksum := layerTarSum.Sum(nil) |
|
| 108 |
+ |
|
| 109 |
+ if img.Checksum != "" && img.Checksum != checksum {
|
|
| 110 |
+ log.Warn("image layer checksum mismatch: computed %q, expected %q", checksum, img.Checksum)
|
|
| 111 |
+ } |
|
| 112 |
+ |
|
| 113 |
+ img.Checksum = checksum |
|
| 90 | 114 |
} |
| 91 | 115 |
|
| 92 | 116 |
img.Size = size |