Extract OCI image config; use it for -r's default command

read_oci_image_config() (src/oci_image.cpp) reads the image config
blob referenced by the manifest and extracts User, ExposedPorts (as
OciExposedPort{port, OciPortProtocol}, parsed from keys like
"3000/tcp"), Env, Volumes, and the effective default command
(Entrypoint ++ Cmd). Refactored the oci-layout/index.json/manifest
loading read_oci_layers() already did into a shared read_oci_manifest()
helper, since this is the first time a second "loud" (spdlog::error
on failure) caller needs the identical validation.

-r/--run now uses the image's own default command when none is given
on the command line, falling back to /bin/sh only if the image sets
neither Entrypoint nor Cmd. User/ExposedPorts/Env/Volumes are captured
but not applied anywhere yet -- that lines up with volumes/networking
still being deferred.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-20 16:35:38 +00:00
parent d009c3777b
commit b8f4680745
4 changed files with 197 additions and 40 deletions
+21
View File
@@ -57,3 +57,24 @@ struct OciImageRef {
// Files that aren't valid OCI archives are silently skipped. Returns nullopt if `dir`
// isn't a readable directory; an empty vector is a valid result (nothing matched).
std::optional<std::vector<OciImageRef>> list_oci_images(const std::filesystem::path& dir);
enum class OciPortProtocol { kTcp, kUdp };
struct OciExposedPort {
int port;
OciPortProtocol protocol;
};
struct OciImageConfig {
std::string user; // config.User, e.g. "git:git"; empty if unset
std::vector<OciExposedPort> exposed_ports; // config.ExposedPorts keys, parsed "<port>/<proto>"
std::vector<std::string> env; // config.Env, e.g. "PATH=..."
std::vector<std::string> volumes; // config.Volumes keys, e.g. "/var/lib/mysql"
std::vector<std::string> command; // config.Entrypoint ++ config.Cmd
};
// Reads the image config blob referenced by the manifest (found via index.json, same
// validation read_oci_layers() already does) and extracts User, ExposedPorts, Env,
// Volumes, and the effective default command (Entrypoint ++ Cmd). Logs a specific
// error and returns nullopt if anything required is missing or malformed.
std::optional<OciImageConfig> read_oci_image_config(const std::filesystem::path& tar_path);