Image
![IT Automation ebook](/sysadmin/sites/default/files/styles/image_cta/public/2021-07/SysAdminGuidetoITAutomation-e-book-medium.jpg?itok=8_5VlQhF)
Photo by Karolina Grabowska from Pexels
A lot of people are moving from Docker to Podman. One of their most frequently asked questions is how to copy their Docker images to Podman.
[ Download now: Podman basics cheat sheet. ]
Some users have suggested just copying them from the container registries to the Podman container storage. But this wastes a lot of bandwidth, and you already have them locally.
Other users have suggested doing a docker save
and a podman load
:
# docker save docker.io/alpine:latest | podman load
Getting image source signatures
Copying blob 8d3ac3489996 done
Copying config c059bfaa84 done
Writing manifest to image destination
Storing signatures
Loaded image: localhost/alpine:latest
# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/alpine latest c059bfaa849c 12 months ago 5.87 MB
Notice that this works, but the name of the image changes. The podman load
of the image does not record the repository where the image came from. For images without a repository, Podman defaults to localhost
rather than docker.io
.
Remove all images from Podman's database:
# podman rmi –all
# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
The best way to copy images from a Docker daemon to Podman container storage is to use the docker-daemon
transport. Podman supports multiple transports for copying images around; by default, it uses the container registry transport (docker), which copies images to and from container registries. Podman can use the docker-daemon
transport to communicate directly with a Docker daemon through the Docker API and copy the image into local storage.
For example, I have the following images stored in Docker:
[ Getting started with containers? Check out this no-cost course. Deploying containerized applications: A technical overview. ]
First I want to use the --format
option on Docker images to create a list of images:
# docker images --format docker-daemon:{{.Repository}}:{{.Tag}}
docker-daemon:<none>:<none>
docker-daemon:<none>:<none>
docker-daemon:nginx:latest
docker-daemon:<none>:<none>
docker-daemon:<none>:<none>
docker-daemon:i386/alpine:edge
docker-daemon:registry.access.redhat.com/ubi8-micro:latest
docker-daemon:fedora:latest
docker-daemon:alpine:latest
Notice that there are a lot of <none><none>
images that I don't want to copy, so I filter them out with grep -v ‘<none>'
:
# docker images --format docker-daemon:{{.Repository}}:{{.Tag}} | grep -v ‘<none>’
docker-daemon:nginx:latest
docker-daemon:i386/alpine:edge
docker-daemon:registry.access.redhat.com/ubi8-micro:latest
docker-daemon:fedora:latest
docker-daemon:alpine:latest
Now I just pipe that list to xargs podman pull
, and Podman will pull each image out of the Docker container storage and into the Podman container storage:
# docker images --format docker-daemon:{{.Repository}}:{{.Tag}} | grep -v ‘<none>’ | xargs podman pull
Getting image source signatures
Copying blob abc66ad258e9 done
Copying blob f931b78377da done
Copying blob d7783033d823 done
Copying blob 43b3c4e3001c done
Copying blob 4553dc754574 done
Copying blob 243243243ee2 done
Copying config 670dcc86b6 done
Writing manifest to image destination
Storing signatures
670dcc86b69df89a9d5a9e1a7ae5b8f67619c1c74e19de8a35f57d6c06505fd4
Getting image source signatures
Copying blob 8329b0e13e56 done
Copying config c9930b809c done
Writing manifest to image destination
Storing signatures
WARNING: image platform ({386 linux [] }) does not match the expected platform ({amd64 linux [] })
c9930b809cbaef2f8784f3b8ed929caa8e95a944815bf91721cb050fe9779613
Getting image source signatures
Copying blob fe7a061dd3ad done
Copying blob 5f70bf18a086 done
Copying config a4b6df2ac2 done
Writing manifest to image destination
Storing signatures
a4b6df2ac2dfb315a4edf1c62f4e44c466ca3ad81d8acc4beba31b07daa9fe77
Getting image source signatures
Copying blob 389adea752cd done
Copying config b78af7a836 done
Writing manifest to image destination
Storing signatures
b78af7a836928efd44317e82c8f2f9c86bb83ae915deef1b58dc6465dfa5436e
Getting image source signatures
Copying blob 8d3ac3489996 done
Copying config c059bfaa84 done
Writing manifest to image destination
Storing signatures
c059bfaa849c4d8e4aecaeb3a10c2d9b3d85f5165c66ad3a4d937758128c4d18
The podman images
command shows the images in Podman container storage with the correct repository name and tags:
While the example above is for rootful Podman, it could also be done with rootless Podman if you put yourself in the docker group (something I don't recommend).
Otherwise, you have to use the docker save
and podman load
commands. Something ugly like:
$ sudo docker save $(sudo docker images --format {{.Repository}}:{{.Tag}} | grep -v '<none>') | podman load
For more information on this subject, I wrote a whole section on image transports in my book Podman in action. Podman-supported transports include:
oci
transport but stores the files using the legacy docker
format.[ Download Dan Walsh's book Podman in action, courtesy of Red Hat. ]
Sadly, it is not as easy to copy containers from Docker to Podman. The best you can do is commit the Docker containers that you want into an image. Then copy the image into the Podman container storage as described above. Once the image is present, you can create a new Podman container off of it.
Transitioning your data from Docker to Podman is reasonably simple to do if you understand container transports. Give docker-daemon
transport a try.
Daniel Walsh has worked in the computer security field for over 30 years. Dan is a Consulting Engineer at Red Hat. He joined Red Hat in August 2001. Dan leads the Red Hat Container Engineering team since August 2013, but has been working on container technology for several years. More about me