Skip to content

Commit cddf362

Browse files
authored
Merge pull request #255 from vbatts/clarify_tar_entry_order
layer: revamp for readability
2 parents 0cf32b8 + f5a91ff commit cddf362

File tree

1 file changed

+149
-34
lines changed

1 file changed

+149
-34
lines changed

layer.md

Lines changed: 149 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,200 @@
1-
# Creating an Image Filesystem Changeset
1+
# Image Layer Filesystem Changeset
22

3-
An example of creating an Image Filesystem Changeset follows.
3+
This document describes how to serialize a filesystem and filesystem changes like removed files into a blob called a layer.
4+
One or more layers are ordered on top of each other to create a complete filesystem.
5+
This document will use a concrete example to illustrate how to create and consume these filesystem layers.
46

5-
An image root filesystem is first created as an empty directory.
6-
Here is the initial empty directory structure for a changeset using the randomly-generated directory name `c3167915dc9d` ([actual layer DiffIDs are generated based on the content](#id_desc)).
7+
## Distributable Format
8+
9+
Layer Changesets for the [mediatype](./media-types.md) `application/vnd.oci.image.layer.tar+gzip` MUST be packaged in [tar archive][tar-archive].
10+
Layer Changesets for the [mediatype](./media-types.md) `application/vnd.oci.image.layer.tar+gzip` MUST NOT include duplicate entries for file paths in the resulting [tar archive][tar-archive].
11+
12+
## Change Types
13+
14+
Types of changes that can occur in a changeset are:
15+
16+
* Additions
17+
* Modifications
18+
* Removals
19+
20+
Additions and Modifications are represented the same in the changeset tar archive.
21+
22+
Removals are represented using "[whiteout](#whiteouts)" file entries (See [Representing Changes](#representing-changes)).
23+
24+
### File Types
25+
26+
Throughout this document section, the use of word "files" includes:
27+
28+
* regular files
29+
* directories
30+
* sockets
31+
* symbolic links
32+
* block devices
33+
* character devices
34+
* FIFOs
35+
36+
### File Attributes
37+
38+
Where supported, MUST include file attributes for Additions and Modifications include:
39+
40+
* Modification Time (`mtime`)
41+
* User ID (`uid`)
42+
* User Name (`uname`) *secondary to `uid`*
43+
* Group ID (`gid `)
44+
* Group Name (`gname`) *secondary to `gid`*
45+
* Mode (`mode`)
46+
* Extended Attributes (`xattrs`)
47+
* Symlink reference (`linkname`)
48+
49+
[Sparse files](https://en.wikipedia.org/wiki/Sparse_file) SHOULD NOT be used because they lack consistent support across tar implementations.
50+
51+
## Creating
52+
53+
### Initial Root Filesystem
54+
55+
The initial root filesystem is the base or parent layer.
56+
57+
For this example, an image root filesystem has an initial state as an empty directory.
58+
The name of the directory is not relevant to the layer itself, only for the purpose of producing comparisons.
59+
60+
Here is an initial empty directory structure for a changeset, with a unique directory name `rootfs-c9d-v1`.
761

862
```
9-
c3167915dc9d/
63+
rootfs-c9d-v1/
1064
```
1165

66+
### Populate Initial Filesystem
67+
1268
Files and directories are then created:
1369

1470
```
15-
c3167915dc9d/
71+
rootfs-c9d-v1/
1672
etc/
1773
my-app-config
1874
bin/
1975
my-app-binary
2076
my-app-tools
2177
```
2278

23-
The `c3167915dc9d` directory is then committed as a plain Tar archive with entries for the following files:
79+
The `rootfs-c9d-v1` directory is then created as a plain [tar archive][tar-archive] with relative path to `rootfs-c9d-v1`.
80+
Entries for the following files:
2481

2582
```
26-
etc/my-app-config
27-
bin/my-app-binary
28-
bin/my-app-tools
83+
./
84+
./etc/
85+
./etc/my-app-config
86+
./bin/
87+
./bin/my-app-binary
88+
./bin/my-app-tools
2989
```
3090

31-
To make changes to the filesystem of this container image, create a new directory, such as `f60c56784b83`, and initialize it with a snapshot of the parent image's root filesystem, so that the directory is identical to that of `c3167915dc9d`.
32-
NOTE: a copy-on-write or union filesystem can make this very efficient:
91+
### Populate a Comparison Filesystem
92+
93+
Create a new directory and initialize it with an copy or snapshot of the prior root filesystem.
94+
Example commands that can preserve [file attributes](#file-attributes) to make this copy are:
95+
* [cp(1)](http://linux.die.net/man/1/cp): `cp -a rootfs-c9d-v1/ rootfs-c9d-v1.s1/`
96+
* [rsync(1)](http://linux.die.net/man/1/rsync): `rsync -aHAX rootfs-c9d-v1/ rootfs-c9d-v1.s1/`
97+
* [tar(1)](http://linux.die.net/man/1/tar): `mkdir rootfs-c9d-v1.s1 && tar --acls --xattrs -C rootfs-c9d-v1/ -c . | tar -C rootfs-c9d-v1.s1/ --acls --xattrs -x` (including `--selinux` where supported)
98+
99+
Any [changes](#change-types) to the snapshot MUST NOT change or affect the directory it was copied from.
100+
101+
For example `rootfs-c9d-v1.s1` is an identical snapshot of `rootfs-c9d-v1`.
102+
In this way `rootfs-c9d-v1.s1` is prepared for updates and alterations.
103+
104+
**Implementor's Note**: *a copy-on-write or union filesystem can efficiently make directory snapshots*
105+
106+
Initial layout of the snapshot:
33107

34108
```
35-
f60c56784b83/
109+
rootfs-c9d-v1.s1/
36110
etc/
37111
my-app-config
38112
bin/
39113
my-app-binary
40114
my-app-tools
41115
```
42116

43-
This example change is going to add a configuration directory at `/etc/my-app.d` which contains a default config file.
44-
There's also a change to the `my-app-tools` binary to handle the config layout change.
45-
The `f60c56784b83` directory then looks like this:
117+
See [Change Types](#change-types) for more details on changes.
118+
119+
For example, add a directory at `/etc/my-app.d` containing a default config file, removing the existing config file.
120+
Also a change (in attribute or file content) to `./bin/my-app-tools` binary to handle the config layout change.
121+
122+
Following these changes, the representation of the `rootfs-c9d-v1.s1` directory:
46123

47124
```
48-
f60c56784b83/
125+
rootfs-c9d-v1.s1/
49126
etc/
50-
.wh.my-app-config
51127
my-app.d/
52128
default.cfg
53129
bin/
54130
my-app-binary
55131
my-app-tools
56132
```
57133

58-
This reflects the removal of `/etc/my-app-config` and creation of a file and directory at `/etc/my-app.d/default.cfg`.
59-
`/bin/my-app-tools` has also been replaced with an updated version.
60-
Before committing this directory to a changeset, because it has a parent image, it is first compared with the directory tree of the parent snapshot, `f60c56784b83`, looking for files and directories that have been added, modified, or removed.
134+
### Determining Changes
135+
136+
When two directories are compared, the relative root is the top-level directory.
137+
The directories are compared, looking for files that have been [added, modified, or removed](#change-types).
138+
139+
For this example, `rootfs-c9d-v1/` and `rootfs-c9d-v1.s1/` are recursively compared, each as relative root path.
140+
61141
The following changeset is found:
62142

63143
```
144+
Added: /etc/my-app.d/
64145
Added: /etc/my-app.d/default.cfg
65146
Modified: /bin/my-app-tools
66147
Deleted: /etc/my-app-config
67148
```
68149

69-
A Tar Archive is then created which contains *only* this changeset:
150+
This reflects the removal of `/etc/my-app-config` and creation of a file and directory at `/etc/my-app.d/default.cfg`.
151+
`/bin/my-app-tools` has also been replaced with an updated version.
152+
153+
### Representing Changes
70154

71-
- Added and modified files and directories in their entirety
72-
- Deleted files or directory marked with a whiteout file
155+
A [tar archive][tar-archive] is then created which contains *only* this changeset:
73156

74-
A whiteout file is an empty file that prefixes the deleted paths basename `.wh.`.
75-
When a whiteout is found in the upper changeset of a filesystem, any matching name in the lower changeset is ignored, and the whiteout itself is also hidden.
76-
As files prefixed with `.wh.` are special whiteout tombstones it is not possible to create a filesystem which has a file or directory with a name beginning with `.wh.`.
157+
- Added and modified files and directories in their entirety
158+
- Deleted files or directories marked with a [whiteout file](#whiteouts)
77159

78-
The resulting Tar archive for `f60c56784b83` has the following entries:
160+
The resulting tar archive for `rootfs-c9d-v1.s1` has the following entries:
79161

80162
```
81-
/etc/my-app.d/default.cfg
82-
/bin/my-app-tools
83-
/etc/.wh.my-app-config
163+
./etc/my-app.d/
164+
./etc/my-app.d/default.cfg
165+
./bin/my-app-tools
166+
./etc/.wh.my-app-config
84167
```
85168

86-
Whiteout files MUST only apply to resources in lower layers.
169+
Where the basename name of `./etc/my-app-config` is now prefixed with `.wh.`, and will therefore be removed when the changeset is applied.
170+
171+
## Applying
172+
173+
Layer Changesets of [mediatype](./media-types.md) `application/vnd.oci.image.layer.tar+gzip` are applied rather than strictly extracted in normal fashion for tar archives.
174+
175+
Applying a layer changeset requires consideration for the [whiteout](#whiteouts) files.
176+
In the absence of any [whiteout](#whiteouts) files in a layer changeset, the archive is extracted like a regular tar archive.
177+
178+
179+
### Changeset over existing files
180+
181+
This section covers applying an entry in a layer changeset, if the file path already exists.
182+
183+
If the file path is a directory, then the existing path just has it's attribute set from the layer changeset for that filepath.
184+
If the file path is any other file type (regular file, FIFO, etc), then the:
185+
* file path is unlinked (See [`unlink(2)`](http://linux.die.net/man/2/unlink))
186+
* create the file
187+
* If a regular file then content written.
188+
* set attributes on the filepath
189+
190+
## Whiteouts
191+
192+
A whiteout file is an empty file with a special filename that signifies a path should be deleted.
193+
A whiteout filename consists of the prefix .wh. plus the basename of the path to be deleted.
194+
As files prefixed with `.wh.` are special whiteout markers, it is not possible to create a filesystem which has a file or directory with a name beginning with `.wh.`.
195+
196+
Once a whiteout is applied, the whiteout itself MUST also be hidden.
197+
Whiteout files MUST only apply to resources in lower/parent layers.
87198
Files that are present in the same layer as a whiteout file can only be hidden by whiteout files in subsequent layers.
88199
The following is a base layer with several resources:
89200

@@ -117,6 +228,8 @@ a/.wh..wh..opq
117228

118229
Implementations SHOULD generate layers such that the whiteout files appear before sibling directory entries.
119230

231+
### Opaque Whiteout
232+
120233
In addition to expressing that a single entry should be removed from a lower layer, layers may remove all of the children using an opaque whiteout entry.
121234
An opaque whiteout entry is a file with the name `.wh..wh..opq` indicating that all siblings are hidden in the lower layer.
122235
Let's take the following base layer as an example:
@@ -139,7 +252,7 @@ bin/
139252
```
140253

141254
This is called _opaque whiteout_ format.
142-
An _opaque whiteout_ file hides _all_ children of the `bin/` including sub-directories and all descendents.
255+
An _opaque whiteout_ file hides _all_ children of the `bin/` including sub-directories and all descendants.
143256
Using _explicit whiteout_ files, this would be equivalent to the following:
144257

145258
```
@@ -151,8 +264,10 @@ bin/
151264

152265
In this case, a unique whiteout file is generated for each entry.
153266
If there were more children of `bin/` in the base layer, there would be an entry for each.
154-
Note that this opaque file will apply to _all_ children, including sub-directories, other resources and all descendents.
267+
Note that this opaque file will apply to _all_ children, including sub-directories, other resources and all descendants.
155268

156269
Implementations SHOULD generate layers using _explicit whiteout_ files, but MUST accept both.
157270

158271
Any given image is likely to be composed of several of these Image Filesystem Changeset tar archives.
272+
273+
[tar-archive]: https://en.wikipedia.org/wiki/Tar_(computing)

0 commit comments

Comments
 (0)