Search code examples
bashdockermanifest

Docker rename manifest or merge 2 images into one


I have a multiarch docker image called someserver:5000/my_image:v1. It is uploaded to some local registry. Image has been made for 2 platforms: linux/arm64 and linux/amd64.

I want to rename this image to someserver:5000/my_release_image:v1. If it was a regular image I could just:

docker pull someserver:5000/my_image:v1
docker tag someserver:5000/my_image:v1 someserver:5000/my_release_image:v1
docker push someserver:5000/my_release_image:v1

But this is a multiarch image done by docker buildx build --platform <ARCHITECTURES> --pull --push ..., so while pulling it I get a revision for my architecture.

How can I retag a multiarchitecture image?


Solution

  • While I was writing this post I've found a solution.

    In the beginning I haven't really gotten how multiarch images are created and what are "manifests" in docker. I thought that some multiarch image someserver:5000/my_image:v1 is like a super-image, but first of all someserver:5000/my_image:v1 is a tag of repository my_image on someserver:5000 registry. There is some manifest that is tagged like this. And it "points" on one or several real images (Correct me if I'm wrong).

    Docker manifests solution

    Solution 1 (If your images are stored locally or online)

    1. (if online - skip this step) Let's assume that somehow you have 2 images on you local machine - someserver:5000/my_image:1 and someserver:5000/my_image:2. Push them into your registry:
    docker push someserver:5000/my_image:1
    docker push someserver:5000/my_image:2
    
    1. Unite them under one manifest someserver:5000/my_release_image:v1:
    docker manifest create someserver:5000/my_release_image:v1 \
    --amend someserver:5000/my_image:1 \
    --amend someserver:5000/my_image:2 
    
    1. Push in into your registry:
    docker manifest push someserver:5000/my_release_image:v1
    

    Solution 2 (If you want too rename manifest)

    Let's say that there is already a manifest with tag latest in my_image repository on your someserver:5000/ registry, but you want to "rename" it to someserver:5000/my_release_image:v1

    1. Get info about the tag
    docker manifest inspect someserver:5000/my_image:latest
    

    It will give you something like this:

    {
       "schemaVersion": 2,
       "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
       "manifests": [
          {
             "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
             "size": 1,
             "digest": "sha256:long_long_hex_number_1",
             "platform": {
                "architecture": "arch1",
                "os": "linux"
             }
          },
          {
             "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
             "size": 13735,
             "digest": "sha256:long_long_hex_number_2",
             "platform": {
                "architecture": "arch2",
                "os": "linux"
             }
          }
       ]
    }
    
    1. Just create a manifest with digests not providing tags:
    docker manifest create someserver:5000/my_release_image:v1 \
    --amend someserver:5000/my_image@sha256:long_long_hex_number_1 \
    --amend someserver:5000/my_image@sha256:long_long_hex_number_2
    
    1. Push in into your registry:
    docker manifest push someserver:5000/my_release_image:v1
    
    1. Delete old manifest:
    docker manifest rm someserver:5000/my_image:latest