github.com/toplink-cn/moby@v0.0.0-20240305205811-460b4aebdf81/layer/layer.go (about) 1 // Package layer is package for managing read-only 2 // and read-write mounts on the union file system 3 // driver. Read-only mounts are referenced using a 4 // content hash and are protected from mutation in 5 // the exposed interface. The tar format is used 6 // to create read-only layers and export both 7 // read-only and writable layers. The exported 8 // tar data for a read-only layer should match 9 // the tar used to create the layer. 10 package layer // import "github.com/docker/docker/layer" 11 12 import ( 13 "context" 14 "errors" 15 "io" 16 17 "github.com/containerd/log" 18 "github.com/docker/distribution" 19 "github.com/docker/docker/pkg/archive" 20 "github.com/opencontainers/go-digest" 21 ) 22 23 var ( 24 // ErrLayerDoesNotExist is used when an operation is 25 // attempted on a layer which does not exist. 26 ErrLayerDoesNotExist = errors.New("layer does not exist") 27 28 // ErrLayerNotRetained is used when a release is 29 // attempted on a layer which is not retained. 30 ErrLayerNotRetained = errors.New("layer not retained") 31 32 // ErrMountDoesNotExist is used when an operation is 33 // attempted on a mount layer which does not exist. 34 ErrMountDoesNotExist = errors.New("mount does not exist") 35 36 // ErrMountNameConflict is used when a mount is attempted 37 // to be created but there is already a mount with the name 38 // used for creation. 39 ErrMountNameConflict = errors.New("mount already exists with name") 40 41 // ErrMaxDepthExceeded is used when a layer is attempted 42 // to be created which would result in a layer depth 43 // greater than the 125 max. 44 ErrMaxDepthExceeded = errors.New("max depth exceeded") 45 ) 46 47 // ChainID is the content-addressable ID of a layer. 48 type ChainID digest.Digest 49 50 // String returns a string rendition of a layer ID 51 func (id ChainID) String() string { 52 return string(id) 53 } 54 55 // DiffID is the hash of an individual layer tar. 56 type DiffID digest.Digest 57 58 // String returns a string rendition of a layer DiffID 59 func (diffID DiffID) String() string { 60 return string(diffID) 61 } 62 63 // TarStreamer represents an object which may 64 // have its contents exported as a tar stream. 65 type TarStreamer interface { 66 // TarStream returns a tar archive stream 67 // for the contents of a layer. 68 TarStream() (io.ReadCloser, error) 69 } 70 71 // Layer represents a read-only layer 72 type Layer interface { 73 TarStreamer 74 75 // TarStreamFrom returns a tar archive stream for all the layer chain with 76 // arbitrary depth. 77 TarStreamFrom(ChainID) (io.ReadCloser, error) 78 79 // ChainID returns the content hash of the entire layer chain. The hash 80 // chain is made up of DiffID of top layer and all of its parents. 81 ChainID() ChainID 82 83 // DiffID returns the content hash of the layer 84 // tar stream used to create this layer. 85 DiffID() DiffID 86 87 // Parent returns the next layer in the layer chain. 88 Parent() Layer 89 90 // Size returns the size of the entire layer chain. The size 91 // is calculated from the total size of all files in the layers. 92 Size() int64 93 94 // DiffSize returns the size difference of the top layer 95 // from parent layer. 96 DiffSize() int64 97 98 // Metadata returns the low level storage metadata associated 99 // with layer. 100 Metadata() (map[string]string, error) 101 } 102 103 // RWLayer represents a layer which is 104 // read and writable 105 type RWLayer interface { 106 TarStreamer 107 108 // Name of mounted layer 109 Name() string 110 111 // Parent returns the layer which the writable 112 // layer was created from. 113 Parent() Layer 114 115 // Mount mounts the RWLayer and returns the filesystem path 116 // to the writable layer. 117 Mount(mountLabel string) (string, error) 118 119 // Unmount unmounts the RWLayer. This should be called 120 // for every mount. If there are multiple mount calls 121 // this operation will only decrement the internal mount counter. 122 Unmount() error 123 124 // Size represents the size of the writable layer 125 // as calculated by the total size of the files 126 // changed in the mutable layer. 127 Size() (int64, error) 128 129 // Changes returns the set of changes for the mutable layer 130 // from the base layer. 131 Changes() ([]archive.Change, error) 132 133 // Metadata returns the low level metadata for the mutable layer 134 Metadata() (map[string]string, error) 135 136 // ApplyDiff applies the diff to the RW layer 137 ApplyDiff(diff io.Reader) (int64, error) 138 } 139 140 // Metadata holds information about a 141 // read-only layer 142 type Metadata struct { 143 // ChainID is the content hash of the layer 144 ChainID ChainID 145 146 // DiffID is the hash of the tar data used to 147 // create the layer 148 DiffID DiffID 149 150 // Size is the size of the layer and all parents 151 Size int64 152 153 // DiffSize is the size of the top layer 154 DiffSize int64 155 } 156 157 // MountInit is a function to initialize a 158 // writable mount. Changes made here will 159 // not be included in the Tar stream of the 160 // RWLayer. 161 type MountInit func(root string) error 162 163 // CreateRWLayerOpts contains optional arguments to be passed to CreateRWLayer 164 type CreateRWLayerOpts struct { 165 MountLabel string 166 InitFunc MountInit 167 StorageOpt map[string]string 168 } 169 170 // Store represents a backend for managing both 171 // read-only and read-write layers. 172 type Store interface { 173 Register(io.Reader, ChainID) (Layer, error) 174 Get(ChainID) (Layer, error) 175 Map() map[ChainID]Layer 176 Release(Layer) ([]Metadata, error) 177 CreateRWLayer(id string, parent ChainID, opts *CreateRWLayerOpts) (RWLayer, error) 178 GetRWLayer(id string) (RWLayer, error) 179 GetMountID(id string) (string, error) 180 ReleaseRWLayer(RWLayer) ([]Metadata, error) 181 Cleanup() error 182 DriverStatus() [][2]string 183 DriverName() string 184 } 185 186 // DescribableStore represents a layer store capable of storing 187 // descriptors for layers. 188 type DescribableStore interface { 189 RegisterWithDescriptor(io.Reader, ChainID, distribution.Descriptor) (Layer, error) 190 } 191 192 // CreateChainID returns ID for a layerDigest slice 193 func CreateChainID(dgsts []DiffID) ChainID { 194 return createChainIDFromParent("", dgsts...) 195 } 196 197 func createChainIDFromParent(parent ChainID, dgsts ...DiffID) ChainID { 198 if len(dgsts) == 0 { 199 return parent 200 } 201 if parent == "" { 202 return createChainIDFromParent(ChainID(dgsts[0]), dgsts[1:]...) 203 } 204 // H = "H(n-1) SHA256(n)" 205 dgst := digest.FromBytes([]byte(string(parent) + " " + string(dgsts[0]))) 206 return createChainIDFromParent(ChainID(dgst), dgsts[1:]...) 207 } 208 209 // ReleaseAndLog releases the provided layer from the given layer 210 // store, logging any error and release metadata 211 func ReleaseAndLog(ls Store, l Layer) { 212 metadata, err := ls.Release(l) 213 if err != nil { 214 log.G(context.TODO()).Errorf("Error releasing layer %s: %v", l.ChainID(), err) 215 } 216 LogReleaseMetadata(metadata) 217 } 218 219 // LogReleaseMetadata logs a metadata array, uses this to 220 // ensure consistent logging for release metadata 221 func LogReleaseMetadata(metadatas []Metadata) { 222 for _, metadata := range metadatas { 223 log.G(context.TODO()).Infof("Layer %s cleaned up", metadata.ChainID) 224 } 225 }