{"id":1084,"date":"2023-11-10T01:46:59","date_gmt":"2023-11-10T09:46:59","guid":{"rendered":"https:\/\/www.gauntletwizard.net\/wordpress\/?p=1084"},"modified":"2023-11-10T02:21:41","modified_gmt":"2023-11-10T10:21:41","slug":"building-and-pushing-multiple-manifests","status":"publish","type":"post","link":"https:\/\/www.gauntletwizard.net\/wordpress\/?p=1084","title":{"rendered":"Building and pushing multiple manifests"},"content":{"rendered":"\n<p>I&#8217;m trying to build multiarch docker images. I&#8217;d like to sand it down as much as possible. In a better world, that would mean just one simple command. It&#8217;s not.<br \/><br \/>Here&#8217;s the first error I got from my simple script:<br \/><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>podman build --platform linux\/amd64 . -t \"${TAG}-amd64\"\npodman build --platform linux\/arm64\/v8 . -t \"${TAG}-arm64\"\npodman manifest create \"$TAG\" \"${TAG}-amd64\" \"${TAG}-arm64\"\n\nError: setting up to read manifest and configuration from \"docker:\/\/account.dkr.ecr.us-east-1.amazonaws.com\/image:tag\": reading manifest docker:\/\/account.dkr.ecr.us-east-1.amazonaws.com\/image:tag: manifest unknown: Requested image not found<\/code><\/pre>\n\n\n\n<p>This didn&#8217;t work, and it turned out the reason was quite simple if obtuse &#8211; <code>podman manifest<\/code> wants to build from the real repositories. As I hadn&#8217;t pushed those images, it couldn&#8217;t find them on the remote repository.<\/p>\n\n\n\n<p>I spent some time searching for a solution to build images locally, then build them into a manifest, and then finally tag them. I found a couple of things that should work, but didn&#8217;t:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>podman manifest add MANIFEST containers-storage:image:tag\nreference \"&#91;overlay@\/home\/ted\/.local\/share\/containers\/storage+\/run\/user\/1000\/containers]docker.io\/library\/image:tag\" does not resolve to an image ID: identifier is not an image<\/code><\/pre>\n\n\n\n<p>I don&#8217;t know why this didn&#8217;t work. According to the docs on <a href=\"https:\/\/github.com\/containers\/image\/blob\/main\/docs\/containers-transports.5.md\">transports<\/a>, <code>containers-storage<\/code> is the transport we can use to inspect local images. This is somewhat consistent in behavior:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>podman build image:tag\npodman tag \npodman inspect image:tag\n...\npodman  inspect containers-storage:repo\/image:tag\n...\npodman inspect containers-storage:image:tag\nError: no such object: \"containers-storage:image:tag\npodman inspect containers-storage:localhost\/image:tag\n...<\/code><\/pre>\n\n\n\n<p>Containers-storage somewhat works, but you have to supply a hostname, which is &#8220;localhost&#8221; for otherwise unspecified images.<\/p>\n\n\n\n<p>Another angle I tried is building both in a singular tag with the manifest flag. This seems like it should work.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>podman build --platform linux\/amd64,linux\/arm64\/v8 . --manifest image:tag<\/code><\/pre>\n\n\n\n<p>This actually worked &#8211;  I didn&#8217;t realize it at first, but it built both architectures:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>podman manifest inspect image:tag\n{\n    \"schemaVersion\": 2,\n    \"mediaType\": \"application\/vnd.docker.distribution.manifest.list.v2+json\",\n    \"manifests\": &#91;\n        {\n            \"mediaType\": \"application\/vnd.oci.image.manifest.v1+json\",\n            \"size\": 2444,\n            \"digest\": \"sha256:ea95462b074c650e6c477f8bf88bcfa0b6a021de7c550e2faca25c7f833bdc5f\",\n            \"platform\": {\n                \"architecture\": \"amd64\",\n                \"os\": \"linux\"\n            }\n        },\n        {\n            \"mediaType\": \"application\/vnd.oci.image.manifest.v1+json\",\n            \"size\": 2444,\n            \"digest\": \"sha256:f1eb75a71b89b3655b845acd79076bc8d640d3db8fb0f24367748fb50b2e6001\",\n            \"platform\": {\n                \"architecture\": \"arm64\",\n                \"os\": \"linux\",\n                \"variant\": \"v8\"\n            }\n        }\n    ]\n}<\/code><\/pre>\n\n\n\n<p>However, when I pushed my image, the wrong format was downloaded on my k8s nodes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>podman push image:tag\n\nContainers:\n  loadtest:\n    Container ID:  containerd:\/\/5d157712c742aa63220c34eb2b5213b0cf580a50c5768406ff434910700a2638\n    Image:         image:tag\n    Image ID:      image:tag@sha256:d0345fbc0ec7c38fdcbedfb90e7b21986e2e9642856e7e2a62a0591d68d48f85<\/code><\/pre>\n\n\n\n<p>A significant amount of consternation later, I realized that because I was using <code>podman push<\/code>, the image was being resolved first, and then just the one architecture was pushed (but with tag for the whole . What I needed to do instead was <code>podman manifest push<\/code>, which pushed the whole manifest and all sub-images.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m trying to build multiarch docker images. I&#8217;d like to sand it down as much as possible. In a better world, that would mean just one simple command. It&#8217;s not. Here&#8217;s the first error I got from my simple script: This didn&#8217;t work, and it turned out the reason was quite simple if obtuse &#8211; &hellip; <a href=\"https:\/\/www.gauntletwizard.net\/wordpress\/?p=1084\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Building and pushing multiple manifests<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/www.gauntletwizard.net\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1084"}],"collection":[{"href":"https:\/\/www.gauntletwizard.net\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gauntletwizard.net\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gauntletwizard.net\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gauntletwizard.net\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1084"}],"version-history":[{"count":3,"href":"https:\/\/www.gauntletwizard.net\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1084\/revisions"}],"predecessor-version":[{"id":1089,"href":"https:\/\/www.gauntletwizard.net\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1084\/revisions\/1089"}],"wp:attachment":[{"href":"https:\/\/www.gauntletwizard.net\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1084"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gauntletwizard.net\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1084"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gauntletwizard.net\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1084"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}