Skip to main content

How to copy Docker images to Podman

Transitioning your data from Docker to Podman is not very difficult to do if you understand container transports.
Image
Differences between containers and images

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

Use docker-daemon transport to copy images from Docker

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:

Image
Output of # docker images repository
(Dan Walsh, CC BY-SA 4.0)

[ 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:

Image
Output of podman images command
(Dan Walsh, CC BY-SA 4.0)

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

Podman-supported transports

For more information on this subject, I wrote a whole section on image transports in my book Podman in action. Podman-supported transports include:

  • Container registry (docker) references a container image stored in a remote container image registry website. Registries store and share container images. For example, docker.io or quay.io.
  • oci is a container image compliant with the Open Container Image Layout Specification. The manifest and layer tarballs (as individual files) are located in the local directory.
  • dir is a container image compliant with the Docker image layout. It's similar to the oci transport but stores the files using the legacy docker format.
  • docker-archive is a container image in Docker image layout that is packed into a TAR archive.
  • oci-archive is a container image compliant with the Open Container Image Layout Specification that is packed into a TAR archive.
  • docker-daemon is an image stored in the Docker daemon's internal storage.
  • container-storage is a container image in a local storage. Podman defaults to using container-storage for local images.

[ Download Dan Walsh's book Podman in action, courtesy of Red Hat. ]

Copy containers from Docker to Podman

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.

Give it a try

Transitioning your data from Docker to Podman is reasonably simple to do if you understand container transports. Give docker-daemon transport a try.

[ Read Kubernetes: Everything you need to know ]

Topics:   Podman   Automation  
Author’s photo

Dan Walsh

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

Try Red Hat Enterprise Linux

Download it at no charge from the Red Hat Developer program.