Skip to content

Commit

Permalink
container: Add application layer to the correct end of the layer stack
Browse files Browse the repository at this point in the history
containertool currently adds the app layer to the beginning of the
layer stack array in the manifest. This results in the app layer
being the first to be unpacked, with the others stacked on top. We
can show this by adding a plain text file as the executable. If we
stack another layer on top with a file of the same name, it should
replace the underlying one but it does not:

    echo first > bar
    swift run containertool --repository localhost:5555/bar bar
    podman run --pull=always -it --rm --entrypoint=cat localhost:5555/bar:latest bar
    # prints: first

    echo second > bar
    swift run containertool --repository localhost:5555/bar bar --from localhost:5555/bar:latest
    podman run --pull=always -it --rm --entrypoint=cat localhost:5555/bar:latest bar
    # prints: first
    # should print: second

Currently containertool is only used to add the application binary
to the application layer. This bug will only cause a problem if the
base layer adds a binary at the same path, because this will override
the application.

This bug probably arose because the specification for the rootfs.diff_ids
field of the image configuration defines the layers as being "in
order from first to last", which could be read ambiguously:
https://github.com/opencontainers/image-spec/blob/main/config.md?plain=1#L220-L222

The specification for the manifest.layers field is much more explicit
about the ordering:
https://github.com/opencontainers/image-spec/blob/fbb4662eb53b80bd38f7597406cf1211317768f0/manifest.md?plain=1#L70-L71

This with this change, the second build and container run in the
example above prints "second" as expected.
  • Loading branch information
euanh committed Jan 30, 2025
1 parent 4d59510 commit bd0e66f
Showing 1 changed file with 5 additions and 7 deletions.
12 changes: 5 additions & 7 deletions Sources/containertool/containertool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,10 @@ enum AllowHTTP: String, ExpressibleByArgument, CaseIterable { case source, desti
config: inherited_config,
rootfs: .init(
_type: "layers",
diff_ids: [
// The diff_id is the digest of the _uncompressed_ layer archive.
// It is used by the runtime, which might not store the layers in
// the compressed form in which it received them from the registry.
digest(of: tardiff)
] + baseimage_config.rootfs.diff_ids
// The diff_id is the digest of the _uncompressed_ layer archive.
// It is used by the runtime, which might not store the layers in
// the compressed form in which it received them from the registry.
diff_ids: baseimage_config.rootfs.diff_ids + [digest(of: tardiff)]
),
history: [.init(created: timestamp, created_by: "containertool")]
)
Expand All @@ -184,7 +182,7 @@ enum AllowHTTP: String, ExpressibleByArgument, CaseIterable { case source, desti
schemaVersion: 2,
mediaType: "application/vnd.oci.image.manifest.v1+json",
config: config_blob,
layers: [application_layer] + baseimage_manifest.layers
layers: baseimage_manifest.layers + [application_layer]
)

// MARK: Upload base image
Expand Down

0 comments on commit bd0e66f

Please sign in to comment.