Get Started with Podman on Oracle Linux
Introduction
Podman provides a lightweight utility for running and managing Open Container Initiative (OCI) compatible containers. It can use existing container images designed for Oracle Container Runtime for Docker, Oracle Cloud Native Environment, and Kubernetes.
Objectives
In this tutorial, you'll learn how to:
- Install Podman
- Pull and run an image from a container registry
- Manage running containers
- Use bind mounts and volumes for container storage
Prerequisites
Minimum of a single Oracle Linux system
Each system should have Oracle Linux installed and configured with:
- A non-root user account with sudo access
- Access to the Internet
Deploy Oracle Linux
Note: If running in your own tenancy, read the linux-virt-labs
GitHub project README.md and complete the prerequisites before deploying the lab environment.
Open a terminal on the Luna Desktop.
Clone the
linux-virt-labs
GitHub project.git clone https://github.com/oracle-devrel/linux-virt-labs.git
Change into the working directory.
cd linux-virt-labs/ol
Install the required collections.
ansible-galaxy collection install -r requirements.yml
Deploy the lab environment.
ansible-playbook create_instance.yml -e localhost_python_interpreter="/usr/bin/python3.6"
The free lab environment requires the extra variable
local_python_interpreter
, which setsansible_python_interpreter
for plays running on localhost. This variable is needed because the environment installs the RPM package for the Oracle Cloud Infrastructure SDK for Python, located under the python3.6 modules.The default deployment shape uses the AMD CPU and Oracle Linux 8. To use an Intel CPU or Oracle Linux 9, add
-e instance_shape="VM.Standard3.Flex"
or-e os_version="9"
to the deployment command.Important: Wait for the playbook to run successfully and reach the pause task. At this stage of the playbook, the installation of Oracle Cloud Native Environment is complete, and the instances are ready. Take note of the previous play, which prints the public and private IP addresses of the nodes it deploys and any other deployment information needed while running the lab.
Install Podman
Open a terminal and connect via SSH to the ol-node-01 instance.
ssh oracle@<ip_address_of_instance>
Install the Podman packages or modules.
Oracle Linux 8:
sudo dnf module install -y container-tools:ol8
Oracle Linux 9:
sudo dnf install -y container-tools
The container-tools module or package installs podman and other container tools, including skopeo and buildah. One essential package is container-selinux, which allows running
podman
as a non-root user on a SELinux-enabled system, which Oracle Linux enables by default.Check the Podman version.
podman version
Get the Podman system information.
podman info
This command displays information about the host, current storage stats, networking, and the configured container registries. For more command options, check out the manual and help pages by running
man podman
orpodman help
.
Pull and Run the Podman Hello World Image
In this tutorial, we'll run all of our commands as a non-root user to ensure that we store pulled images under the user's home directory and that the containers are run as rootless or without the need for root or sudo privileges.
When pulling container images, we pull them from a container registry. Oracle Linux configures Podman and Skopeo to use the Oracle Container Registry at container-registry.oracle.com
or Docker Hub at docker.io
as the defaults.
Run the Hello World image to confirm Podman is working and can access image registries.
podman run quay.io/podman/hello
Example Output:
[oracle@ol-node-01 ~]$ podman run quay.io/podman/hello Trying to pull quay.io/podman/hello:latest... Getting image source signatures Copying blob d08b40be6878 done Copying config e2b3db5d4f done Writing manifest to image destination Storing signatures !... Hello Podman World ...! .--"--. / - - \ / (O) (O) \ ~~~| -=(,Y,)=- | .---. /` \ |~~ ~/ o o \~~~~.----. ~~ | =(X)= |~ / (O (O) \ ~~~~~~~ ~| =(Y_)=- | ~~~~ ~~~| U |~~ Project: https://github.com/containers/podman Website: https://podman.io Documents: https://docs.podman.io Twitter: @Podman_io [oracle@ol-node-01 ~]$
List locally stored images, their names, and their IDs.
podman images
Example Output:
REPOSITORY TAG IMAGE ID CREATED SIZE quay.io/podman/hello latest e2b3db5d4fdf 2 weeks ago 82.3 kB
There is often more than one command to get the same result. You can also list locally stored images using
podman image list
or the variationpodman image ls
.
Search Container Registries for Images
View the default container registries Podman configures during installation on Oracle Linux.
cat /etc/containers/registries.conf | grep unqualified
The output identifies
["container-registry.oracle.com", "docker.io"]
as a list ofhost:[port]
registries that Podman uses when trying to pull an unqualified image. An unqualified image does not contain the registry name as part of the image when passed on the Podman command line. You can add further registries to this list as needed.Search for images containing the word
oracle
.podman search oracle
While a registry's implementation can affect the search results, the default search returns only the first 25 images per container registry matching the search criteria.
Repeat the search and limit the results to 5 images per registry.
podman search oracle --limit 5
Rerun the search, this time showing only the first ten entries while including the additional columns containing their star rating, official status, and automated information.
podman search oracle --limit 10 --compatible
List the image version tags for the oraclelinux images.
When requesting the image version tags, you must specify a fully qualified image name containing the specific registry name to search. Due to the default result limits, you may not see all possible entries.
podman search --list-tags container-registry.oracle.com/os/oraclelinux
You can extend the number of results by using the
--limit
option and increasing its value. Using--limit 50
will increase the results to 50 rather than the default 25.You can further parse your results using
grep
to search for a specific string in the output.Get a list of official images.
podman search oracle -f=is-official
You can also use the
--compatible
option to see theOK
status, which indicates the image is the official image.
Pull, Inspect, and List Images
A container image is a read-only template used to generate a container. It contains all the requirements for a service or application to run.
Tagging an image enables you to identify different versions of the same image. Often, an image might include a default tag of latest
so that Podman users can quickly identify the most recent version of the image. However, Oracle Linux images don't use this tag as it can result in significant jumps between distribution releases rather than update levels. Instead, Oracle Linux images use the slim or release version tag.
Pull the oraclelinux:8 image.
podman pull container-registry.oracle.com/os/oraclelinux:8
Note: You provide a fully qualified image name in the command.
List all of your locally pulled images.
podman images
The
IMAGE ID
column shows each image's unique identifier (ID), a SHA256 hash of the local image JSON configuration. Therefore, the ID values may differ from one environment to the next.Pull down the oraclelinux:9 image.
This time, we'll pull the image from the Github repository.
podman pull ghcr.io/oracle/oraclelinux:9
Again, list all the locally pulled images.
podman images
Try pulling an unqualified image.
podman pull oracle8
The name oracle8 is a short-name reference, as it does not contain the registry name and path. Without this information, Podman prompts you to select one of the default registries to search by using the up and down arrows for navigation. If you hit
Enter
and get an authentication error, that indicates the registry requires a login to perform the search. Regardless, the search will fail because this image is not an Oracle image name.You can escape back to the prompt by typing
Ctrl-C
.Get the configuration and metadata information for an image.
podman inspect oraclelinux:8 | head -n 6
The
head
command limits the output to the first six lines and helps identify the image ID, registry, and tag information.Example Output:
[ { "Id": "8c71bed6d6a721d4aa07420bbefa51b224d20979951305e90498a7341aa03630", "Digest": "sha256:499559fe8352e259bccc17410c9d4c6da2a85db41479141b6aac9809b2f3e726", "RepoTags": [ "container-registry.oracle.com/os/oraclelinux:8"
Compare the
Id
field to theIMAGE ID
column information in thepodman images
command output. The first 12 characters match the value in theIMAGE ID
column, which is enough uniqueness to identify separate images in the list.Use a filter to show specific pulled images.
podman images --filter reference=oraclelinux:8
Please refer to the upstream podman-images documentation for additional filter options.
Work With Containers
Containers are running instances of images. Each container starts with an image and loads into run time using the parameters provided when it's created or run.
Create a Container
Get the oraclelinux:9 image ID.
export OL9=$(podman images --filter reference=oraclelinux:9 | awk 'NR==2{print $3; exit}')
The
NR==2
grabs the second row, while the{print $3; exit}
grabs the third column.Create a container using the oraclelinux:9 image, giving it the name
test01
and using the image ID.podman create -it --name test01 $OL9
The option
-i
will keep the STDIN open, making the container interactive, while adding thet
will open a pseudo-tty to allow running commands. The Oracle Linux images run/bin/bash
by default.The output displays the new
CONTAINER_ID
after container creation.List all containers created with the
podman ps
command.podman ps
The results show that there are no actively running containers. Creating a container does not automatically raise it to a running state unless you use a specific command option, which we will see later.
List all containers, regardless of the status.
podman ps -a
The output's first column shows the container ID (
CONTAINER ID
). It is different from the image ID seen when viewing images. Notice that theSTATUS
column for the new container shows it isCreated
but notUp
.The
NAMES
column shows the name you assigned to the container when creating it. If you do not assign a name, Podman assigns a unique and random name, as you can see for the hello:latest container.Try to create another container using the same image and name.
podman create -it --name test01 $OL9
The command fails with the message:
Error: creating container storage: the container name "<container_name>" is already in use by <container_id>. You have to remove that container to be able to reuse that name: that name is already in use
You can create and run multiple containers from the same image, but each container must have a unique name.
Start the container.
podman start test01
Examine the status of the container.
podman ps
The output shows the status of the
test01
container is nowUp
.
Run a Container
Create another container and start it in a single command.
podman run -it --name test02 $OL9
The running container presents you with a Bash prompt.
Show the Oracle Linux version of the running container.
cat /etc/oracle-release
Exit out of the container.
exit
Check the status of all containers.
podman ps -a
Exiting causes the
test02
container to stop, but Podman does not delete it, and we can restart it later. TheCREATED
column shows when we built the container, and theSTATUS
column shows the time since itExited
or was stopped.Stop the test01 container.
podman stop test01
Verify the state of the container.
podman ps -a
All the containers show in an
Exited
state.Start the test01 container without opening its interactive command prompt.
podman start test01
Verify the container starts.
podman ps
The STATUS column shows
Up
and how long the container has been up. Remember, we can also use the-a
option to see all containers and their status.
Attach to a Container
Attach to the test01 container to access its running shell.
podman attach test01
Notice the prompt changes.
Exit from the container again.
exit
Verify again that exiting the container has also stopped it.
podman ps -a
Start the test01 container again and access its shell in a single command.
podman start --attach test01
This time, exit the container without stopping it by pressing
Ctrl-P
and thenCtrl-Q.
Check the status of the container and verify it is still up and running.
podman ps -a
Pause a Container
Note: Pausing a container requires cgroup v2, enabled by default in Oracle Linux 9. If cgroup v2 is not available, you'll get the following error:
Error: can not pause containers on rootless containers with cgroup V1: this container does not have a cgroup
If you see this error, then skip to the next section.
Pause the test01 container.
Pausing a container temporarily halts its operation. It freezes all the running processes inside a container in their current state.
However, shutting down and restarting the host system running the paused container will not preserve the state of those processes. You can only pause and unpause while the host system remains running.
podman pause test01
Note: You can pause multiple containers with the command by listing each separated by a
space
or all containers by using the-a
option.Verify the container status reports as paused.
podman ps -a
Resume the paused container and check its status.
podman unpause test01 podman ps -a
Execute a Command in a Container
You can run commands in a running container in multiple ways. This includes using the exec
command or the podman create
and podman run
commands when creating or spinning up a new container.
Execute a command in the running test01 container.
podman exec test01 cat /etc/oracle-release
Spin up a new container to run the same command.
podman run --name test03 --rm $OL9 cat /etc/oracle-release
The
--rm
option automatically removes the container after the command completes.
Stop a Container
Containers are stopped with SIGTERM by default. The stop
command will wait 10 seconds before using SIGKILL to forcibly stop the container. The order of the running processes inside the container and the types of processes can affect how the container shuts down and how long it may take. For example, many shells ignore the SIGTERM signal used when stopping a container.
You can override the wait time with the --time <secs>
option.
Start a new container called test04 using the
-d
option to run it in the background and the--rm
option to remove it after stopping it.podman run -dt --name test04 $OL9
Stop the container.
podman stop test04
After 10 seconds, a warning is presented. The container has not been stopped with SIGTERM, and after the default timeout, it is stopped with SIGKILL. The shell running in the container prevented SIGTERM from stopping it.
Start a new container and change the stop signal to SIGHUP using the
--stop-signal=SIGHUP
option.podman run -dt --rm --stop-signal=SIGHUP --name test05 $OL9
Stop the container.
podman stop test05
The container stops without timing out or displaying any warnings.
Restart container test04.
podman start test04
Stop the container using a signal.
Another way to stop a container is to use the podman-kill command and pass the
--signal
option. The default is SIGKILL.podman kill --signal SIGHUP test04
View Container Logs
The podman logs command returns any logs present for one or more containers.
View the log for the test01 container.
You will see any logs available for the container, similar to running
tail
on an Oracle Linux log file.podman logs test01
The output is not overly interesting as we have not run many commands within the container. If you pass two or more container names to the
podman logs
command, its output uses the container ID value to identify which container the entry is from.
Remove Containers
Remove the test04 container.
podman rm test04
You can pass multiple container names or container IDs in any combination on the command line when removing containers.
Start the container test01.
podman start test01
Try removing the
test01
container.podman rm test01
Note: The output displays the following error:
`Error: cannot remove container <container_id> as it is running - running or paused containers cannot be removed without force: container state improper
Use the
--force
option to remove the runningtest01
container without stopping it first.podman rm --force test01
Note: Forcefully removing a container can also be used to remove containers created by different container engines, such as Buildah, even if Podman does not know about the container.
Remove all of the remaining containers.
podman rm -a
Verify all of the containers are gone.
podman ps -a
The output will show an empty list.
Remove Images
List the locally stored images available.
podman images
Remove the oraclelinux:8 image.
podman rmi oraclelinux:8
You can also remove the image using its full or partial image ID rather than its name. Remember that partial image ID values must start with the leftmost character and read from left to right.
Remove all of the remaining images.
podman rmi -a
Verify all of the images are gone.
podman ps -a
The output will show an empty list.
Use a Bind Mount for Data Storage
A bind mount attaches a host filesystem mount to the container for persistent storage after removing the container. This example demonstrates using a bind mount as the document root for a containerized Python HTTP server.
Make a directory.
mkdir ~/data
Create a Dockerfile.
cat << EOF | tee ~/Dockerfile > /dev/null FROM ghcr.io/oracle/oraclelinux:9 WORKDIR /data RUN dnf -y install python3.12 python3.12-libs python3.12-pip python3.12-setuptools python3.12-wheel && \ rm -rf /var/cache/dnf && \ mkdir -p /data ENTRYPOINT /usr/bin/python3.12 -m http.server 8000 EOF
FROM
pulls theoraclelinux:9
image.WORKDIR
sets the working directory when the container runs.RUN
executes the command in a shell.ENTRYPOINT
configures the container to run the Simple Python HTTP server.
Build the image.
podman build --tag oraclelinux:pyhttp .
--tag
specifies the name of the resulting image if the build process completes successfully.- If imageName does not include a registry name, the registry name localhost prepends to the image name.
Show the new image.
podman images
Start a container based on the new image.
podman run -d -p 8080:8000 --name webapp1 -v ~/data:/data:Z oraclelinux:pyhttp
-d
starts the container as a daemon process.-p
creates a port forward from 8080 on the host to 8000 in the container.--name
assignswebapp1
as the container name.-v
maps the bind mount~/data/
on the host to/data
in the container.
The
:Z
creates a private unshared label ofcontainer_file_t
. Podman requires this additional suffix on the mount due to SELinux. If we want to share the mount between multiple containers, use:z
.Verify the container is running.
podman ps -a
The container shows a status of UP.
Show the
/opt/data
directory is empty on the host system.ll ~/data
Use
curl
to show the/data
directory within the container is empty.curl localhost:8080
This command works because the container's
/data
directory is a bind mount to the host system's~/data
directory.The HTTP Server's root directory uses
/data
with the working directory set where the server starts.Add files to the host system's
~/data
directory.for i in {1..10}; do touch ~/data/file${i}; done
Using the script creates ten empty files.
Verify the script created the files successfully.
ll ~/data
Verify that the HTTP server within the container also sees the newly created files.
curl localhost:8080
The steps show the successful use of a bind mount to allow reading and writing to the host from within a container. Any data written to the host persists after a container stops or gets removed.
Stop and remove the containers.
podman ps -a podman stop webapp1 podman rm webapp1
Using Volumes with Containers
A volume is a storage device created and managed by Podman. It can be created directly using the podman volume
command or during container creation.
Create a volume using
podman volume
.podman volume create my_vol
List volumes.
podman volume ls
Remove a volume.
podman volume rm my_vol
Start a container and create a volume attached to it.
podman run -it -v my_data:/data --name box1 oraclelinux:9
The container starts an interactive shell and presents a prompt.
-v
creates the volumemy_data
and mounts/data
within the container.
An anonymous volume is created without passing the name
my_data
to it. It does not have a reference name and is identified only by its unique ID.Get a listing of files in
/data
from within the container.ls -l /data
Create a test file in the volume and verify it exists.
touch /data/sample.txt ls -l /data
Leave and exit the container.
exit
Show the container has stopped.
podman ps -a
Inspect the container and get a list of volumes used.
podman inspect -f '{{.Mounts}}' box1
-f
formats the output and shows only the container volume details.
Restart the container and check if the file still exists.
podman restart box1 podman exec box1 ls -l /data
The command
exec
runs the requested command against the restarted container.Stop and then remove the container.
podman stop box1 podman rm box1
Check the volume still exists.
podman ps -a podman volume ls
podman ps -a
shows that the container has been removed, whilepodman volume ls
shows that the volume remains.Mount the existing volume to a new container.
podman run -it --mount 'type=volume,src=my_data,dst=/data2' --name box2 oraclelinux:9
--mount
: takes the following key-value pairs when mounting an existing volume.type
: the type of storage to mountsrc
: the name or unique id of a volumedst
: the mount point within the container
The container mount point
/data2
shows that the new container mount point does not need to match the original mount point.The data in the volume persists.
ls -l /data2
Leave the container.
exit
Remove the container and all unused volume storage.
podman rm -v box2 podman ps -a podman volume ls podman volume prune podman volume ls
The
podman volume prune
removes all volumes not used by at least one container. If you only want to remove a single volume, usepodman volume rm <VOLUME_NAME>
.
Summary
By completing this tutorial, you've demonstrated your skills and ability to use Podman to manage containers on Oracle Linux.