Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: October 24, 2024
Podman is an open-source container engine. Its main benefit is that it’s daemonless. Accordingly, when we run Podman, a daemon (a background process) isn’t started for it. Therefore, we don’t need the root privileges generally required when a container engine is run as a daemon. However, the Docker container engine runs a daemon by default; therefore, Docker runs as the root user. We can still take advantage of the Podman container engine by running the Podman inside a Docker container.
In this tutorial, we’ll learn about installing and using Podman inside a Docker container.
The only prerequisite we need to perform is to install Docker on Linux (Ubuntu).
The root user owns the Unix socket and a Docker engine binds to the Unix socket. Therefore, a user needs to prefix docker commands with sudo by default. However, we can bypass this requirement by adding Docker user/s to the docker group, thereby granting root privileges to users:
$ sudo groupadd docker
$ sudo usermod -aG docker $USER
$ newgrp docker
Afterward, we can run a docker command without sudo such as docker run hello-world.
Having installed Docker and enabled root privileges for non-sudo users, let’s run Podman inside a Docker container. However, we first need to run a Docker container to run Podman. We use the container image quay.io/podman/stable, provided by Red Hat, especially to run Podman within a container. Further, running a container as a specific user (root or other) limits the privileges within the container to those of the user.
When we launch a Docker engine container, we should include the –privileged flag. Linux kernel filesystems can be mounted in the read-write mode within the container when we launch a Docker container with the –privileged flag. Conversely, a container is launched in read-only mode when we don’t use the –privileged flag. We need the –privileged option so that Podman-associated privileged processes and processes with Linux capabilities in the user namespace can be written to the kernel filesystems.
Further, “Linux capabilities” is a term for a subset of Linux privileges within a user namespace. Accordingly, processes within a user namespace can only access the resources and security-related attributes (root directory, GIDs, and UIDs) assigned to the namespace. In the context of rootless containers, the container engine is limited to the capabilities within a user namespace. These limitations apply even to the root user.
To run Podman within a Docker container, we first need to run a Docker container. Therefore, let’s launch a Docker container run from the quay.io/podman/stable image:
$ docker run
-it
--privileged
quay.io/podman/stable bash
Accordingly, the -it option starts an interactive TTY terminal within the container. Furthermore, the command installs Podman in the container. We can verify this with the podman command:
$ [root@39ca237c6764 /]# podman
Manage pods, containers and images
Usage:
podman [options] [command]
Available Commands:
attach Attach to a running container
build Build an image using instructions from Containerfiles
commit Create new image based on the changed container
create Create but do not start a container
exec Run a process in a running container
help Help about any command
image Manage images
images List images in local storage
info Display podman system information
run Run a command in a new container
start Start one or more containers
stop Stop one or more containers
update Update an existing container
version Display the Podman version information
volume Manage volumes
Options:
-c, --connection string Connection to use for remote Podman service (CONTAINER_CONNECTION)
--help Help for podman
We can run a Podman container inside the Docker container. Let’s run the hello-world image:
$ podman run hello-world
Resolved "hello-world" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull quay.io/podman/hello:latest...
Getting image source signatures
Copying blob 81df7ff16254 done |
Copying config 5dd467fce5 done |
Writing manifest to image destination
!... Hello Podman World ...!
.--"--.
/ - - \
/ (O) (O) \
~~~| -=(,Y,)=- |
.---. /` \ |~~
~/ o o \~~~~.----. ~~
| =(X)= |~ / (O (O) \
~~~~~~~ ~| =(Y_)=- |
~~~~ ~~~| U |~~
Project: https://github.com/containers/podman
Website: https://podman.io
Desktop: https://podman-desktop.io
Documents: https://docs.podman.io
YouTube: https://youtube.com/@Podman
X/Twitter: @Podman_io
Mastodon: @[email protected]
After that, let’s verify the Podman images downloaded:
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
quay.io/podman/hello latest 5dd467fce50b 4 months ago 787 kB
Let’s list the Podman containers, running or stopped:
$ podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a6f245fc2523 quay.io/podman/hello:latest /usr/local/bin/po... 2 minutes ago Exited (0) 2 minutes ago vibrant_yonath
The container engine stores the Podman-related artifacts in the /var/lib/containers/storage directory when we launch a Podman container as the root user:
$ cd /var/lib/containers/storage
$ ls -l
-rw-r--r-- 1 root root 122880 Oct 18 19:46 db.sql
drwx------ 2 root root 4096 Oct 18 19:46 libpod
drwx------ 3 root root 4096 Oct 18 19:46 overlay-containers
drwx------ 3 root root 4096 Oct 18 19:46 overlay-images
Furthermore, we can list the containers stored in the overlay-containers directory:
$ cd overlay-containers
$ ls -l
drwx------ 3 root root 4096 Oct 18 19:46 a6f245fc2523714e62f69b9dcc4d0e5ea8ab9de967558464a003d5ffe1535d15
Similarly, we can list the container images stored in the overlay-images directory:
$ ls -l
drwx------ 2 root root 4096 Oct 18 19:46 5dd467fce50b56951185da365b5feee75409968cbab5767b9b59e325fb2ecbc0
We can use Podman to build images and run containers, and pods. It’s important to understand that “rootless containers” doesn’t imply that containers can’t be run as root. Podman containers can be run as the root user, as we demonstrated.
When we want to run a Podman container as a non-root user, we use the podman user that’s provided by the container image. Therefore, let’s launch a Docker container run from the quay.io/podman/stable image, but this time as the podman user:
$ docker run
--user podman
-it
--privileged
quay.io/podman/stable bash
The command pre-installs Podman in the container; therefore, we can start to use Podman. Let’s run a Podman container inside the Docker container using the hello-world image:
$ podman run hello-world
Resolved "hello-world" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull quay.io/podman/hello:latest...
Getting image source signatures
Copying blob 81df7ff16254 done |
Copying config 5dd467fce5 done |
Writing manifest to image destination
!... Hello Podman World ...!
.--"--.
/ - - \
/ (O) (O) \
~~~| -=(,Y,)=- |
.---. /` \ |~~
~/ o o \~~~~.----. ~~
| =(X)= |~ / (O (O) \
~~~~~~~ ~| =(Y_)=- |
~~~~ ~~~| U |~~
Project: https://github.com/containers/podman
Website: https://podman.io
Desktop: https://podman-desktop.io
Documents: https://docs.podman.io
YouTube: https://youtube.com/@Podman
X/Twitter: @Podman_io
Mastodon: @[email protected]
Let’s list the Podman images downloaded:
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
quay.io/podman/hello latest 5dd467fce50b 4 months ago 787 kB
Furthermore, let’s list the Podman containers:
$ podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6d860d4a0ae9 quay.io/podman/hello:latest /usr/local/bin/po... 2 minutes ago Exited (0) 2 minutes ago frosty_rosalind
The container engine stores the Podman-related artifacts in the /home/podman/.local/share/containers directory when we launch a Podman container as a non-root user, such as the podman user:
$ cd /home/podman/.local/share/containers
$ ls -l
-rw-r--r-- 1 podman podman 122880 Oct 18 20:08 db.sql
drwx------ 2 podman podman 4096 Oct 18 20:08 libpod
drwx------ 3 podman podman 4096 Oct 18 20:08 overlay-containers
drwx------ 3 podman podman 4096 Oct 18 20:08 overlay-images
We can list the containers stored in the overlay-containers directory:
$ cd overlay-containers
$ ls -l
drwx------ 3 podman podman 4096 Oct 18 20:08 6d860d4a0ae962e4f99369eaf3d219fb383461c6611fa89c37f84b33404c0b38
Similarly, we can list the container images stored in the overlay-images directory:
$ ls -l
drwx------ 2 podman podman 4096 Oct 18 20:08 5dd467fce50b56951185da365b5feee75409968cbab5767b9b59e325fb2ecbc0
Similarly, we can run other Podman commands.
Let’s check for possible issues and how to troubleshoot them.
When we try to run a Docker container as a non-root user, we get an error message:
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock
We can fix this issue by prefixing the command with sudo or by adding the user running the command to the docker group.
When we try to run Podman inside a Docker container without including the –privileged option, we can get an error message similar to one of the following:
Error: mounting storage for container
Error: configure storage: mount
The container engine causes this issue because, by default, it mounts the Linux kernel’s filesystem in read-only mode. We can fix this issue by including the –privileged flag in the docker run command.
When using Podman, we can get issues related to UIDs and GIDs, as an example:
potentially insufficient UIDs or GIDs available in user namespace : Check /etc/subuid and /etc/subgid if configured locally and run "podman system migrate"
This error message indicates insufficient UIDs and GIDs. The podman user supports only 5000 UIDs by default. We can modify the container image to support more UIDs, such as 65000.
In this article, we learned about running Podman inside a Docker container. We can run the Docker container as the root user or a non-root user. However, we should run the Docker container by including the –privileged option in the docker run command to run Podman within it. Further, we can avoid most issues by using a supported operating system.
As always, the Docker commands’ scripts used in this article are available over on GitHub.