Get Started with Podman on Oracle Linux

14
3
Send lab feedback

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.

  1. Open a terminal on the Luna Desktop.

  2. Clone the linux-virt-labs GitHub project.

    git clone https://github.com/oracle-devrel/linux-virt-labs.git
  3. Change into the working directory.

    cd linux-virt-labs/ol
  4. Install the required collections.

    ansible-galaxy collection install -r requirements.yml
  5. 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 sets ansible_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

  1. Open a terminal and connect via SSH to the ol-node-01 instance.

    ssh oracle@<ip_address_of_instance>
  2. 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.

  3. Check the Podman version.

    podman version
  4. 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 or podman 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.

  1. 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 ~]$
  2. 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 variation podman image ls.

Search Container Registries for Images

  1. 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 of host:[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.

  2. 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.

  3. Repeat the search and limit the results to 5 images per registry.

    podman search oracle --limit 5
  4. 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
  5. 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.

  6. Get a list of official images.

    podman search oracle -f=is-official 

    You can also use the --compatible option to see the OK 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.

  1. 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.

  2. 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.

  3. Pull down the oraclelinux:9 image.

    This time, we'll pull the image from the Github repository.

    podman pull ghcr.io/oracle/oraclelinux:9
  4. Again, list all the locally pulled images.

    podman images
  5. 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.

  6. 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 the IMAGE ID column information in the podman images command output. The first 12 characters match the value in the IMAGE ID column, which is enough uniqueness to identify separate images in the list.

  7. 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

  1. 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.

  2. 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 the t 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.

  3. 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.

  4. 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 the STATUS column for the new container shows it is Created but not Up.

    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.

  5. 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.

  6. Start the container.

    podman start test01
  7. Examine the status of the container.

    podman ps

    The output shows the status of the test01 container is now Up.

Run a Container

  1. 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.

  2. Show the Oracle Linux version of the running container.

    cat /etc/oracle-release
  3. Exit out of the container.

    exit
  4. 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. The CREATED column shows when we built the container, and the STATUS column shows the time since it Exited or was stopped.

  5. Stop the test01 container.

    podman stop test01
  6. Verify the state of the container.

    podman ps -a

    All the containers show in an Exited state.

  7. Start the test01 container without opening its interactive command prompt.

    podman start test01
  8. 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

  1. Attach to the test01 container to access its running shell.

    podman attach test01

    Notice the prompt changes.

  2. Exit from the container again.

    exit
  3. Verify again that exiting the container has also stopped it.

    podman ps -a
  4. Start the test01 container again and access its shell in a single command.

    podman start --attach test01
  5. This time, exit the container without stopping it by pressing Ctrl-P and then Ctrl-Q.

  6. 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.

  1. 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.

  2. Verify the container status reports as paused.

    podman ps -a
  3. 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.

  1. Execute a command in the running test01 container.

    podman exec test01 cat /etc/oracle-release
  2. 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.

  1. 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 
  2. 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.

  3. 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
  4. Stop the container.

    podman stop test05

    The container stops without timing out or displaying any warnings.

  5. Restart container test04.

    podman start test04
  6. 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.

  1. 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

  1. 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.

  2. Start the container test01.

    podman start test01
  3. 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

  4. Use the --force option to remove the running test01 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.

  5. Remove all of the remaining containers.

    podman rm -a
  6. Verify all of the containers are gone.

    podman ps -a

    The output will show an empty list.

Remove Images

  1. List the locally stored images available.

    podman images  
  2. 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.

  3. Remove all of the remaining images.

    podman rmi -a
  4. 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.

  1. Make a directory.

    mkdir ~/data
  2. 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 the oraclelinux: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.
  3. 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.
  4. Show the new image.

    podman images
  5. 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 assigns webapp1 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 of container_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.

  6. Verify the container is running.

    podman ps -a

    The container shows a status of UP.

  7. Show the /opt/data directory is empty on the host system.

    ll ~/data
  8. 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.

  9. 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.

  10. Verify the script created the files successfully.

    ll ~/data
  11. 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.

  12. 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.

  1. Create a volume using podman volume.

    podman volume create my_vol
  2. List volumes.

    podman volume ls
  3. Remove a volume.

    podman volume rm my_vol
  4. 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 volume my_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.

  5. Get a listing of files in /data from within the container.

    ls -l /data
  6. Create a test file in the volume and verify it exists.

    touch /data/sample.txt
    ls -l /data
  7. Leave and exit the container.

    exit
  8. Show the container has stopped.

    podman ps -a
  9. 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.
  10. 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.

  11. Stop and then remove the container.

    podman stop box1
    podman rm box1
  12. Check the volume still exists.

    podman ps -a
    podman volume ls

    podman ps -a shows that the container has been removed, while podman volume ls shows that the volume remains.

  13. 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 mount
    • src: the name or unique id of a volume
    • dst: 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.

  14. The data in the volume persists.

    ls -l /data2
  15. Leave the container.

    exit
  16. 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, use podman 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.

For More Information

2024-12-21T15:12:41.648Z