How to share a Docker image without a registry with Podman

Sometimes, well, probably very rarely, you may have the use case where you have a Docker image that you want to share with a colleague or friend, but you don’t have a registry to upload it to. Luckily, there is another way you can do that with podman by using the podman save and podman load commands. It’s super simple, here is how it’s done.

Saving the image to a tarball

The first step is to save the image to a tar ball. That’s where podman save comes in, which is not to be confused with podman export. The difference between the two is that podman save saves a image to a file (aka a compressed tarball), while podman export exports a container to a file.

podman save comes only with a couple of options:

$ podman save --help
Save image(s) to an archive

Description:
  Save an image to docker-archive or oci-archive on the local machine. Default is docker-archive.

Usage:
  podman save [options] IMAGE [IMAGE...]

Examples:
  podman save --quiet -o myimage.tar imageID
  podman save --format docker-dir -o ubuntu-dir ubuntu
  podman save > alpine-all.tar alpine:latest

Options:
      --compress              Compress tarball image layers when saving to a directory using the 'dir' transport. (default is same compression type as source)
      --format string         Save image to oci-archive, oci-dir (directory with oci manifest type), docker-archive, docker-dir (directory with v2s2 manifest type) (default "docker-archive")
  -m, --multi-image-archive   Interpret additional arguments as images not tags and create a multi-image-archive (only for docker-archive)
  -o, --output string         Write to a specified file (default: stdout, which must be redirected)
  -q, --quiet                 Suppress the output
      --uncompressed          Accept uncompressed layers when copying OCI images

In its simplest form, you can just invoke podman save -o my-file.tar <image name>. Note that by default podman save writes to stdout so you can also redirect the save from there to a file (or anywhere else) via podman save > my-file.tar <image name>.

Here is an example using the -o option:

$ podman save -o gvenzl-oracle-free-23.5-slim.tar localhost/gvenzl/oracle-free:23.5-slim
Copying blob 53a5bb4f0279 done   |
Copying blob 94e555c6b8cd done   |
Copying blob ef6bbbd9d7cb done   |
Copying blob efd5b62e86c9 done   |
Copying blob e5eb5e3fb515 done   |
Copying blob d6905b105e5d done   |
Copying config 56f860e2a4 done   |
Writing manifest to image destination
$ ls -alh gvenzl-oracle-free-23.5-slim.tar
-rw-r--r--. 1 gvenzl gvenzl 1.5G Aug 14 16:06 gvenzl-oracle-free-23.5-slim.tar

Loading the tarball as an image

Once your colleague or friend has the file, it can be loaded using podman load, not to be confused with podman import. Here again, podman load loads the image from the tarball while podman import creates a new image from a tarball but none of the run instructions such as ENTRYPOINT, CMD, or USER. In other words, podman import will just give you the contents of the tarball file as a new image but that image cannot spin up any containers for you.

Just like podman save, podman load is also fairly straight forward to use. It has the following options:

% podman load --help
Load image(s) from a tar archive

Description:
  Loads an image from a locally stored archive (tar file) into container storage.

Usage:
  podman load [options]

Options:
  -i, --input string   Read from specified archive file (default: stdin)
  -q, --quiet          Suppress the output

To load the image as is, just run podman load -i <tarball file>:

% podman load -i gvenzl-oracle-free-23.5-slim.tar
Loaded image: localhost/gvenzl/oracle-free:23.5-slim
% podman images
REPOSITORY                    TAG         IMAGE ID      CREATED       SIZE
localhost/gvenzl/oracle-free  23.5-slim   56f860e2a4f1  10 hours ago  1.54 GB

Running the loaded image

Congrats, you now have the image loaded on another machine:

 % podman run --name test -p 1521:1521 -e ORACLE_PASSWORD=LetsTest1 -e APP_USER=gerald -e APP_USER_PASSWORD=LetsTest1 gvenzl/oracle-free:23.5-slim
CONTAINER: starting up...
CONTAINER: first database startup, initializing...
CONTAINER: uncompressing database data files, please wait...
CONTAINER: done uncompressing database data files, duration: 3 seconds.
CONTAINER: starting up Oracle Database...

LSNRCTL for Linux: Version 23.0.0.0.0 - Production on 14-AUG-2024 16:39:07

Copyright (c) 1991, 2024, Oracle.  All rights reserved.

Starting /opt/oracle/product/23ai/dbhomeFree/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 23.0.0.0.0 - Production
System parameter file is /opt/oracle/product/23ai/dbhomeFree/network/admin/listener.ora
Log messages written to /opt/oracle/diag/tnslsnr/fb5db676fb14/listener/alert/log.xml
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_FREE)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC_FOR_FREE)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 23.0.0.0.0 - Production
Start Date                14-AUG-2024 16:39:07
Uptime                    0 days 0 hr. 0 min. 0 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Default Service           FREE
Listener Parameter File   /opt/oracle/product/23ai/dbhomeFree/network/admin/listener.ora
Listener Log File         /opt/oracle/diag/tnslsnr/fb5db676fb14/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_FREE)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))
The listener supports no services
The command completed successfully
ORACLE instance started.

Total System Global Area 1603726640 bytes
Fixed Size		    5360944 bytes
Variable Size		  771751936 bytes
Database Buffers	  822083584 bytes
Redo Buffers		    4530176 bytes
Database mounted.
Database opened.

CONTAINER: Resetting SYS and SYSTEM passwords.

User altered.


User altered.

CONTAINER: Creating app user for default pluggable database.

Session altered.


User created.


Grant succeeded.

CONTAINER: DONE: Creating app user for default pluggable database.

#########################
DATABASE IS READY TO USE!
#########################

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top