Subscribe to the feed

The newly released Podman 4.0 includes the new podman image scp command, a useful command to help you manage and transfer container images.

Have you ever built an image only to realize that you actually need it on a user account other than root, requiring you to rebuild the image again in rootless mode?

Or have you built an image on one machine but run containers on the image using multiple different machines? Now you need to set up an account on a registry, push the image to the registry, Secure Shell (SSH) to each device you want to run the image on, and then pull the image.

The podman image scp command solves both of these annoying scenarios as quickly as they occur.

You can copy a root image to a non-root account like this:

$ podman image scp root@localhost::IMAGE USER@localhost::

Or copy an image from one machine to another with this command:

$ podman image scp me@192.168.68.122::IMAGE you@192.168.68.128::

Transferring images between local machines has traditionally involved an image registry like Quay.io, connecting to the internet, and pushing and pulling the image.

[ You might also be interested in learning 5 handy flags that make the Podman user experience better. ]

With Podman's podman image scp, you can transfer images between local and remote machines without requiring an image registry.

Podman takes advantage of its SSH support to copy images between machines, and it also allows for local transfer. Registryless image transfer is useful in a couple of key scenarios:

  1. Doing a local transfer between users on one system
  2. Sharing images over the network

The next sections cover these examples in more detail.

1. Do local transfer between users on a system

You can use the podman image scp command to transfer images between local users by using this command:

$ podman image scp USERNAME@localhost::$IMAGE root@localhost::

Specifying the destination is actually optional. If root is specified in the source, the default $USER is assumed as the destination. If a user is specified and validated, root is assumed as the destination. For example, this transfers $IMAGE to root:

$ podman image scp USERNAME@localhost::$IMAGE

This feature allows users to build images using either rootful or rootless permissions and transfer them seamlessly wherever they are needed. The command does not require sudo to execute but prompts for validation midcommand if your user is not included in /etc/sudoers.

You can also copy an image from root to a user account:

# podman image scp $IMAGE USERNAME@localhost::

Alternately, use sudo with a specific source and destination:

$ sudo podman image scp root@localhost::$IMAGE USERNAME@localhost::

Here's an example:

$ cat Containerfile
FROM registry.fedoraproject.org/fedora:35
RUN dnf install -y podman
CMD ["podman", "run", "-dt", "alpine"]

This simple Containerfile still takes some time to process if you run it for multiple user accounts. The dnf command alone takes a long time to process.

$ podman build –file=Containerfile
	...
	...
	Complete!
--> 18a64048b45
STEP 3/3: CMD ["podman", "run", "-dt", "alpine"]
COMMIT
--> fbf02ebb4eb
Fbf02ebb4eb454abf76715e6a7b0200c9e9a0add086cfb7a60eeed47a9b4e1c9

Oops, you realize you just built this on the wrong user. You meant to build it again as root:

$ sudo podman build –file=Containerfile

Or you could push the image, become root, and pull it from the registry, like this:

$ podman push \
fbf02ebb4eb454abf76715e6a7b0200c9e9a0add086cfb7a60eeed47a9b4e1c9 \ 	dir:/tmp/scpimg
	Getting image source signatures
Copying blob a4220bc9b4f9 done  
Copying blob ea810b5c3ace done  
Copying config fbf02ebb4e done  
Writing manifest to image destination
Storing signatures
	
$ sudo podman pull dir:/tmp/scpimg
	Getting image source signatures
Copying blob a4220bc9b4f9 done  
Copying blob ea810b5c3ace done  
Copying config fbf02ebb4e done  
Writing manifest to image destination
Storing signatures
Fbf02ebb4eb454abf76715e6a7b0200c9e9a0add086cfb7a60eeed47a9b4e1c9

Both of these options are time-consuming and potentially require a third-party registry.

The podman image scp command simply copies the image between users:

$ podman image scp \
fbf02ebb4eb454abf76715e6a7b0200c9e9a0add086cfb7a60eeed47a9b4e1c9 \
root@localhost::
Copying blob a4220bc9b4f9 done  
Copying blob ea810b5c3ace done  
Copying config fbf02ebb4e done  
Writing manifest to image destination
Storing signatures
Getting image source signatures
Copying blob ea810b5c3ace skipped: already exists  
Copying blob a4220bc9b4f9 skipped: already exists  
Copying config fbf02ebb4e done  
Writing manifest to image destination
Storing signatures
Loaded image(s): sha256:fbf02ebb4eb454abf76715e6a7b0200c9e9a0add086cfb7a60eeed47a9b4e1c9

This one command eliminates the need for a registry to temporarily store the image.

[ Keep key commands at your fingertips. Download the Intermediate Linux cheat sheet. ]

2. Share images between machines over the network

You can also use the podman image scp command remotely. For example, to copy an image from a remote machine to your local system, type:

podman image scp USER@CONNECTION::$IMAGE

Or, to copy an image from your local machine to a remote machine, run:

$ podman image scp $IMAGE USERNAME@CONNECTION::

This example copies the image from a remote machine to a different remote machine:

podman image scp USER1@CONNECTION1::$IMAGE USER2@CONNECTION2::

Building an image on a machine and then distributing it to many systems can be even more laborious. You need to push the image to a registry, then SSH into each box you want the image on, and finally pull it back to that system. Given that you probably already have SSH configured to connect to the remote machines, just use podman image scp to copy the image to each machine instead. All that's required is to configure the SSH connections using the podman system connection add command. Execute the following:

$ podman system connection list
Name     URI                                       Identity                  Default
ubuntu   ssh://myuser@192.168.68.[...]podman.sock  /home/tux/.ssh/id_ubuntu  true

$ podman image scp \ 
fbf02ebb4eb454abf76715e6a7b0200c9e9a0add086cfb7a60eeed47a9b4e1c9 \
ubuntu::
Copying blob 72e830a4dff5 done   
Copying config 85f9dc67c7 done   
Writing manifest to image destination
Storing signatures
Loaded image(s): sha256:fbf02ebb4eb454abf76715e6a7b0200c9e9a0add086cfb7a60eeed47a9b4e1c9

This single command has the same effect as pushing to and pulling from a remote registry without any of the related complications.

An example

First, create a new SSH key using ssh-keygen, send that key over to the remote SSH directory using ssh-copy-id, and place that new key in the authorized_keys file on the remote machine. Next, create a new connection using the following command:

$ ssh-copy-id -i <.pub file> -o IdentitiesOnly=yes REMOTE_USER_NAME@192.168.122.1

Next, create the connection using the podman system connection add command:

$ podman system connection add CONNECTION -i ~/.ssh/id_ed25519 \      
REMOTE_USER_NAME@192.168.122.1:22/run/user/1000/podman/podman.sock

Podman names the new connection CONNECTION and uses the recently created SSH key. You need to specify the Podman socket on the remote machine so that the program knows where to execute commands.

Adding this connection allows you to refer to this address as CONNECTION. Say you have an image named my_image you want to send to this remote machine. Executing podman image scp my_image CONNECTION:: results in:

$ podman image scp my_image CONNECTION::
Copying blob 72e830a4dff5 done   
Copying config 85f9dc67c7 done   
Writing manifest to image destination
Storing signatures
Loaded image(s): my_image:latest

Podman copies my_image to the remote CONNECTION. You can also retrieve an image from your newly established remote machine by executing:

$ podman image scp CONNECTION::my_image
Copying blob 72e830a4dff5 done   
Copying config 85f9dc67c7 done   
Writing manifest to image destination
Storing signatures
Loaded image(s): my_image:latest

Finally, the image does not even have to be located locally. Put two connections into the command, one as a source and the other as a destination. In this example, you previously set up two additional connections, one named ONE and the second called TWO.

$ podman image scp ONE::my_image TWO::
Copying blob 72e830a4dff5 done   
Copying config 85f9dc67c7 done   
Writing manifest to image destination
Storing signatures
Loaded image(s): my_image:latest

How it works

Podman creates two new processes that utilize either a podman image save or podman image load. Here is a simple example:

$ podman image scp root@localost::$IMAGE $USER@localhost::

The first new process is forked off the main podman process, executing a sudo podman image save. Then a second process is started by running the podman image load command. The alternative command is:

$ podman image scp $USER@localost::$IMAGE root@localhost::

This transfers from user storage to root storage. Transferring between rootful and rootless storage is possible because image scp does not enter the Podman namespace until it executes the proper load and saves commands. Not entering the Podman namespace allows podman image scp to act as a wrapper function when performing local tasks.

Copy images

The podman image scp command circumvents retrieval of images from a traditional registry by utilizing sshd and executing new Podman processes. The ability to transfer images between users or networks allows more flexibility in sharing images with different machines. This feature's use in edge and secure environments are interesting to consider, as are the everyday uses.


About the authors

Charlie is an intern with Red Hat's Container Runtimes team working on products like Podman and Buildah. He is currently a computer science major at the College of the Holy Cross.

Read full bio

Daniel Walsh has worked in the computer security field for over 30 years. Dan is a Senior Distinguished 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. 

Dan helped developed sVirt, Secure Virtualization as well as the SELinux Sandbox back in RHEL6 an early desktop container tool. Previously, Dan worked Netect/Bindview's on Vulnerability Assessment Products and at Digital Equipment Corporation working on the Athena Project, AltaVista Firewall/Tunnel (VPN) Products. Dan has a BA in Mathematics from the College of the Holy Cross and a MS in Computer Science from Worcester Polytechnic Institute.

Read full bio
UI_Icon-Red_Hat-Close-A-Black-RGB

Browse by channel

automation icon

Automation

The latest on IT automation for tech, teams, and environments

AI icon

Artificial intelligence

Updates on the platforms that free customers to run AI workloads anywhere

open hybrid cloud icon

Open hybrid cloud

Explore how we build a more flexible future with hybrid cloud

security icon

Security

The latest on how we reduce risks across environments and technologies

edge icon

Edge computing

Updates on the platforms that simplify operations at the edge

Infrastructure icon

Infrastructure

The latest on the world’s leading enterprise Linux platform

application development icon

Applications

Inside our solutions to the toughest application challenges

Original series icon

Original shows

Entertaining stories from the makers and leaders in enterprise tech