Podman Volumes Explained: Named Volumes vs Host Mounted Volumes (How to Create & Manage)

If you haven't already, check out my Getting started with Podman guide.

When we run containers in podman, there will be instances where we need to persist data outside of the container lifetime. This is achieved with volumes.

What is a volume?

A volume is simply a file or folder that is mounted to a specific path in the container and any data written there will not be lost when the container is removed.

Named volumes vs Host mounted volumes

With podman and generally docker there are two common types of volumes:

A named volume, which is a volume managed and created by podman. It already has all the correct permissions allocated and is usually the default option.

A host mounted volume, which is a file or folder not created or managed by podman that you mount into your containers. You will have to ensure that the correct ownership and permissions are set otherwise your container will throw an access denied error. More on that later.

Working with Named Volumes

Here is the most useful / used volume commands with podman:

podman volume --help # show all volume commands with descriptions

podman volume ls # list all your volumes
podman volume inspect {name | id} # inspect the details of that volume

podman volume create {name} # create a volume, name is optional
podman volume rm {name | id} # remove (delete) a volume
podman volume prune # prune (delete) all volumes NOT in use

An awesome quality of life (QOL) feature of podman, is that we don't need to create our named volumes before we run our containers, podman will do that for us. All we need to do is specify the named volume and where to mount it along with the appropriate SELinux label if you are using SELinux.

Here is an example command of this in action:

podman run \
  --name my-pgsql \ # container name
  -v pg-data:/var/lib/postgresql/data:z \ # named volume mount
  -p 5432:5432 \ # port mapping
  -e POSTGRES_PASSWORD=secret \ # pgsql env var
  postgres:latest

Using the -v flag we specified the named volume pg-data and mounted it to /var/lib/postgresql/data path within the container along with the z SELinux label.

Here is an example of a host mounted volume:

podman run \
  --name my-nginx \ # container name
  -v ~/my-nginx-site:/usr/share/nginx/html:ro,Z \ # host mounted volume
  -p 8080:80 \ # port mapping
  nginx:latest

In this example we also used the -v flag, but instead of mounting a named volume we used a path on the host and mounted that to the /usr/share/nginx/html path inside of the container with the appropriate SELinux labels.

Access Denied Errors

When using host mounted volumes it's inevitable that you will run into an access denied error. This can also occur with named volumes but it's super rare.

The reason our containers receive an access denied error is usually due to one or more of the following:

  • Insufficient File or folder ownership
  • Insufficient Permissions
  • SELinux labels (if using SELinux)

Let's cover how we can tackle these different scenarios:

Understanding user namespaces

Before we can tackle those issues we need to understand a key Linux kernel feature that enables container isolation: user namespaces.

Think of a user namespace as a bubble where the user and group IDs (UID and GID) are mapped to different IDs within that bubble. This means our containers believe they are running as normal users -- such as nginx with UID 101 -- but on the host, this is mapped to a different UID like 10100 which typically has very limited privileges:

Namespaces diagram

This is important to understand because when containers interact with the file system (reading or writing to volumes), the kernel uses the host UID for permission checks. If that host UID does not have sufficient privileges or the correct ownership you will get an access denied error.

Fixing ownership with podman unshare

NOTE: Before we continue, make sure you understand how Linux handles file and folder ownership, including how permissions work for the user, group and others (using r, w and x).

To make our lives easier with user namespaces, the podman team has given us the podman unshare command.

It executes any command you give it within the container user namespace, allowing us to use linux commands like chown (change owner) to change ownership of files or folders without worrying about what the container user id maps back to on host as the user namespace handles that for us.

Let's see this in action in an example where we grant nginx container user test file that we mounted:

# ownership before, using `ls -l`:
-rw-rw-r-- 1 jason jason 0 May 27 18:55 myfile.txt

# change ownership of file
podman unshare chown nginx myfile.txt

# ownership after, using `ls -l`
-rw-rw-r-- 1 10100 jason 0 May 27 18:55 myfile.txt

We can also recursively change ownership of a folder and its contents using the -R flag:

podman unshare chown -R nginx my-dir

Fixing user or group permissions

This is pretty simple as we don't need to think about user namespaces, we can simply use the linux chmod command to assign read, write or execute permissions depending on our needs.

Here is an example of adding write permission to our myfile.txt for user from our earlier example.

# permissions before using `ls -l`:
-r--rw-r-- 1 10100 jason 0 May 27 18:55 myfile.txt

# adding write (w) permission for user with chmod:
chmod u+w myfile.txt

# permissions after using `ls -l`:
-rw-rw-r-- 1 10100 jason 0 May 27 18:55 myfile.txt

SELinux labels

Unfortunately, I'm not too familiar with SELinux labels, but I'm sure if you are using it that you know how to manage or assign labels.

Here is the official documentation.

When I become more familiar with it, I will update this section.

In summary

We covered the basics of volumes and how to triage those pesky access denied errors from rootless containers.

However, my guide does not cover everything and in case you missed it, here are some helpful documentation links:

The next step on your podman journey would be Learning How to Use Networks in Podman.

Thanks for reading and I hoped this helped you on your podman journey!