Objective: Attach persistent storage to containers so data survives beyond the container's life cycle, and access running containers for interactive work and troubleshooting.
Overview
A container's writable layer disappears when the container is removed, which is a problem for anything that needs to keep data — a database's files, uploaded content, or logs. Volumes solve this by storing data outside the container's own filesystem. Separately, administrators need ways to reach into a running container to inspect or interact with it directly.
Key Concepts
Why persistent storage matters
By design, containers are meant to be disposable and easily replaced. Any data that must outlive a specific container instance — and, in Kubernetes/OpenShift, must be able to follow a pod if it's rescheduled to a different node — needs to live in storage that exists independently of the container.
Bind mounts vs. named volumes
A bind mount maps a specific directory on the host filesystem directly into the container. A named volume is storage managed by the container engine itself (stored under its own directory tree), referenced by name rather than a host path — generally preferred because it's portable and doesn't depend on host-specific paths.
# Bind mount: host path -> container path
$ podman run -d --name db -v /var/local/mysql-data:/var/lib/mysql:Z \
registry.redhat.io/rhel8/mysql-80
# Named volume, created and managed by Podman
$ podman volume create mysql-vol
$ podman run -d --name db -v mysql-vol:/var/lib/mysql:Z \
registry.redhat.io/rhel8/mysql-80
The :Z / :z SELinux label
On SELinux-enforcing hosts (the default on RHEL), a mounted volume needs a matching SELinux label or the container process will be denied access to it. Appending :Z to a volume mount relabels the content for exclusive use by that one container; :z labels it for shared use by multiple containers.
In Kubernetes/OpenShift: PersistentVolumes and Claims
At the orchestration layer, storage is abstracted further: a PersistentVolume (PV) represents an actual piece of storage in the cluster, and a PersistentVolumeClaim (PVC) is a request for storage by an application — the application only references the claim, not the underlying storage details, which keeps pod definitions portable across environments.
Accessing a running container
Several commands let you reach into a running container without stopping it, from a quick one-off command to a full interactive shell.
| Command | Purpose |
|---|---|
podman exec <name> <cmd> |
Run a single command inside a running container |
podman exec -it <name> /bin/bash |
Open an interactive shell inside a running container |
podman attach <name> |
Attach your terminal to the container's main process |
podman cp |
Copy files between the host and a container |
Working with It
Prefer named volumes over bind mounts for portability — a named volume doesn't assume a specific directory exists on every host that might run the container.
podman exec -it ... /bin/bash gives you a separate shell process to poke around with; podman attach connects to the container's actual main process, so typing in the wrong place can send input to your application itself.
On an SELinux-enforcing host, a bind mount or volume mounted without :Z/:z often results in the containerized process getting a permission-denied error even though the Linux file permissions look correct — check ausearch -m avc if this happens.
Persisting data and inspecting it interactively
$ podman volume create app-data
$ podman run -d --name app -v app-data:/data:Z quay.io/example/app:latest
$ podman exec -it app /bin/bash
[container]$ ls /data
[container]$ exit
Watch Out For
On an SELinux-enforcing host, a bind mount or volume mounted without :Z/:z often results in the containerized process getting a permission-denied error even though the Linux file permissions look correct — check ausearch -m avc if this happens.
Key Terms
- Bind mount
- A direct mapping of a host directory into a container's filesystem.
- Named volume
- Storage managed by the container engine and referenced by name, not a host path.
- :Z / :z
- SELinux relabeling options for volume mounts (exclusive vs. shared access).
- PersistentVolume (PV)
- A cluster-level representation of actual storage, in Kubernetes/OpenShift.
- PersistentVolumeClaim (PVC)
- A request for storage by an application, decoupled from the underlying PV.
Review Questions
- What is the key difference between a bind mount and a named volume?
- Why might a container fail to write to a correctly-permissioned bind-mounted directory on a RHEL host, and how do you fix it?
- In Kubernetes/OpenShift terms, what is the difference between a PersistentVolume and a PersistentVolumeClaim?
- What command would you use to get an interactive bash shell inside a running container?
- Why is
podman execgenerally safer for debugging thanpodman attach?