Understanding Podman: How It Differs from Docker and Practical Commands
This article explains what Podman is, compares its daemon‑less, rootless architecture to Docker's daemon‑based model, and provides step‑by‑step installation, configuration, and command‑line examples for managing containers, images, volumes, and networking on Linux.
Podman overview
Podman is an open‑source OCI‑compatible container runtime that runs on most Linux distributions. It provides a Docker‑compatible CLI but does not require a long‑running daemon and can operate without root privileges.
Architectural differences
Docker relies on a central daemon ( dockerd) that runs as root; Podman launches containers directly without a daemon.
Docker's stack is dockerd → containerd → containerd‑shim → runc. Podman replaces dockerd with a per‑container conmon process that fulfills the role of containerd‑shim.
Because no privileged daemon is needed, Podman's process tree is simpler and more suitable for rootless operation.
Command‑line compatibility
Podman implements the same subcommands as Docker, making migration straightforward.
podman run # create and start a container
podman start # start an existing container
podman ps # list containers
podman stop # stop a container
podman restart # restart a container
podman exec # run a command inside a container
podman images # list local images
podman pull # download an image
podman push # upload an image
podman build # build an image from a DockerfileInstallation on RHEL‑compatible systems
# yum -y install podmanRegistry accelerator configuration (version 7 example)
# vim /etc/containers/registries.conf
registries = ["docker.io"]
[[docker.io]]
location = "j3m2itm3.mirror.aliyuncs.com"Running a container – step‑by‑step
# podman run -d --name httpd docker.io/library/httpd
# podman images
# podman psThe output shows the image ID, creation time, size, and confirms that the container is running.
Inspecting a container
# podman inspect -l | grep IPAddressWhen running rootless the IPAddress field may be null, indicating that the container does not have a dedicated network namespace.
Logs and process inspection
# podman logs --latest
# podman top httpdStopping and removing containers
# podman stop --latest
# podman rm --latestRootless operation requirements
Install crun and set runtime = "crun" in /usr/share/containers/containers.conf (or /etc/containers/containers.conf) if the default runc does not support cgroup v2.
Install slirp4netns and fuse‑overlayfs to enable user‑namespace networking and overlay storage.
Configure /etc/subuid and /etc/subgid so each non‑root user has a unique UID/GID range, e.g. zz:100000:65536.
Adjust net.ipv4.ip_unprivileged_port_start if a rootless container needs to bind a privileged port (<1024).
Using volumes with user namespaces
Mount a host directory into a container while preserving file ownership by adding --userns=keep-id:
# podman run -it -v "$(pwd)"/data:/data --userns=keep-id docker.io/library/busybox /bin/shBuilding and pushing an image
Example builds a custom Nginx image, tags it, logs in to Docker Hub, and pushes it.
# cat Dockerfile
FROM docker.io/library/centos
ENV PATH /usr/local/nginx/sbin:$PATH
ADD files/nginx-1.20.1.tar.gz /usr/src
RUN useradd -r -M -s /sbin/nologin nginx && \
yum -y install pcre-devel openssl openssl-devel gd-devel gcc gcc-c++ make && \
mkdir -p /var/log/nginx && \
cd /usr/src/nginx-1.20.1 && \
./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-debug \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_image_filter_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--http-log-path=/var/log/nginx/access.log \
--error-log-path=/var/log/nginx/error.log && \
make && make install
CMD ["nginx","-g","daemon off"] # podman build -t nginx .
# podman tag docker.io/library/nginx:latest docker.io/1314444/test:latest
# podman login docker.io
Username: 1314444
Password: ********
Login Succeeded!
# podman push docker.io/1314444/test:latestConfiguration files hierarchy
Podman reads configuration in the following order (higher priority overrides lower):
/usr/share/containers/containers.conf /etc/containers/containers.conf $HOME/.config/containers/containers.confSimilar precedence applies to storage.conf and registries.conf. Example storage.conf to enable the overlay driver and fuse‑overlayfs:
# vi /etc/containers/storage.conf
[storage]
driver = "overlay"
mount_program = "/usr/bin/fuse-overlayfs"Rootless namespace limits and privileged ports
To allow a non‑root user to bind ports below 1024, set the kernel parameter:
# echo 'net.ipv4.ip_unprivileged_port_start=80' >> /etc/sysctl.conf
# sysctl -p
net.ipv4.ip_unprivileged_port_start = 80After this, a rootless container can expose port 80:
# podman run -d -p 80:80 httpdAliasing Docker to Podman
For seamless transition, add an alias in ~/.bashrc:
echo "alias docker=podman" >> ~/.bashrc
source ~/.bashrcKey takeaways
Podman eliminates the central daemon, simplifying the process tree and enabling true rootless operation.
All Docker commands are supported, so existing Docker workflows (run, build, push, etc.) work unchanged.
Rootless mode requires additional runtime components (crun, slirp4netns, fuse‑overlayfs) and proper UID/GID mapping.
Configuration files allow fine‑grained control over storage driver, registries, and runtime.
Port binding below 1024 in rootless mode is possible by adjusting net.ipv4.ip_unprivileged_port_start.
Source: https://blog.csdn.net/qq_48289488/article/details/121905018
Java Web Project
Focused on Java backend technologies, trending internet tech, and the latest industry developments. The platform serves over 200,000 Java developers, inviting you to learn and exchange ideas together. Check the menu for Java learning resources.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
