【Linux】Podman 容器实践 | Redhat
本专栏文章持续更新,新增内容使用蓝色表示。
背景
早期开源项目采用 LAMP 架构(Linux + Apache + MySQL + PHP),随着应用复杂度提升,部署和运维挑战日益增加。2006年亚马逊推出 AWS 服务,开创了云计算商业化先河,也为容器技术的发展铺平了道路。
虚拟化技术作为云计算的基础设施,为微服务架构的兴起创造了条件。而容器技术则在虚拟化基础上,提供了更加轻量级的解决方案。
一、什么是容器?
容器本质上是一种特殊的进程,通过内核级隔离技术实现容器间运行环境的完全隔离。这种隔离机制确保了各个容器互不影响,为应用程序提供了一种轻量级的打包和部署解决方案。容器技术不仅简化了应用程序的依赖管理,还极大地提升了部署效率和环境一致性。
1.1 核心支撑技术
1.1.1 Control Groups (cgroups)
cgroups 是 Linux 内核特性,负责资源管理和分配。它主要控制:
-
CPU 资源分配和限制
-
内存使用量和交换空间管理
-
磁盘 I/O 带宽控制
-
网络优先级设置
1.1.2 Namespace 隔离机制
Namespace 提供进程间的隔离环境,包括:
-
PID Namespace:进程 ID 隔离
-
Network Namespace:网络栈隔离
-
Mount Namespace:文件系统挂载点隔离
-
UTS Namespace:主机名和域名隔离
-
IPC Namespace:进程间通信资源隔离
-
User Namespace:用户和组 ID 隔离
1.1.3 安全增强型 Linux (SELinux)
SELinux 提供强制访问控制机制(MAC),为容器环境增加额外的安全层,防止权限提升和资源滥用。
1.2【重要】容器与虚拟机的区别
虽然虚拟机和容器在用户体验上相似,甚至容器启动速度更快,但两者的架构本质不同:
1.2.1 虚拟机架构特点
-
通过 Hypervisor 虚拟化层抽象硬件资源
-
每个虚拟机包含完整的操作系统
-
资源开销较大,启动速度较慢
-
提供完全隔离的运行环境
1.2.2 容器架构特点
-
直接运行在主机操作系统上
-
共享主机操作系统内核(通过docker引擎借助主机的操作系统)
-
资源利用率高,启动速度快(秒级)
-
容器内部只包含应用及其所有依赖(二进制文件、库、配置文件)
1.3 有根容器和无根容器
在容器主机上,用户可以选择以 root 用户或普通用户身份运行容器:
1)Rootful 容器:以 root 权限运行,具有系统级访问能力,但存在安全风险。
2)Rootless 容器(无根容器):以非特权用户运行,安全性更高但功能受限
-
无法绑定特权端口(1024以下)
-
部分系统操作受到限制
由于容器继承父进程的地址空间,在 root 用户下运行的容器需要特别关注安全配置。
1.4 Podman 与 Docker 的主要区别
1)无守护进程 (Daemon-less):不需要一个常驻后台进程来管理容器,更加轻量和安全。
2)Rootless 模式:这是最重要的特性。普通用户无需 root 权限即可直接运行和管理容器,极大地提升了安全性。以上所有命令都可以在非 root 用户下执行。
3)Pod 原生支持:直接支持管理 Kubernetes 风格的 Pod(一组共享资源的容器)。
1.5 容器特点
1)环境一致性:解决"开发-测试-生产"环境差异问题,避免因环境配置导致的运行异常。
2)版本管理:支持容器镜像版本控制,方便回滚和版本追踪。
3)可移植性:轻松跨环境迁移,从开发到生产环境无缝过渡。
4)临时性:容器生成的数据通常为临时的,重要数据需通过卷(volume)持久化存储。
5)镜像复用:一个镜像可启动多个容器实例,可以类比面向对象中的类和对象关系。
1.6 容器镜像
容器镜像基于应用程序代码、运行时配置、系统库和依赖项构建而成,构建完成后为只读状态,不可修改,想要更新需要重新构建镜像版本。
容器镜像统一存储在镜像仓库中管理。这个仓库在 docker 叫做 repository ,在红帽的 podman 中为了区分叫做容器注册表 registry ,实际上是一个内容。
注:容器可以理解为是运行中的镜像。
1.7 容器运行时与编排
容器运行依赖底层运行时(如 runc、crun),这些运行时实现容器生命周期管理。在 Docker 中称为容器引擎,在 Podman 中采用无守护进程架构。
Kubernetes——容器编排工具,现版本可以称为云原生的操作系统。
注:这部分的具体内容会在【Kubernetes 学习与面试必知】专栏中具体介绍。
OpenShift——Kubernetes 的企业级发行版,拥有图形化界面,封装了k8s并增加了一些功能,如 Web 管理界面、监控、审计等,,简化容器编排复杂度。
二、Podman 使用
Podman 在设计时就有意保持了与 Docker CLI(命令行界面)的高度兼容性。 对于绝大多数日常命令,只需要将 podman 换成 docker 即可。命令的格式、选项和参数都完全相同,降低了用户从 Docker 迁移到 Podman 的学习成本和迁移门槛。
2.1 镜像管理
1)查看镜像:podman images (列出本地镜像)
2)搜索镜像:podman search <镜像名> (从仓库搜索,如 podman search nginx)
3)拉取镜像:podman pull <镜像名:标签> (下载镜像到本地,如 podman pull ubuntu:22.04)
4)构建镜像:podman build -t <镜像名:标签> <路径> (根据 Dockerfile 构建镜像,如 podman build -t myapp:1.0 .)
补充:
-t 是 --tag 的缩写,目的是为了给镜像一个有意义的标识符,方便后续的使用、管理和分享。
标签(Tag)用于用于区分同一镜像的不同版本、不同变体或不同构建。
镜像名和标签的关系就像 “书名” 和 “版本号”。
5)推送镜像:podman push <镜像名> <仓库地址> (将镜像推送到远程仓库)
6)删除镜像:podman rmi <镜像名或ID> (删除本地镜像,如 podman rmi alpine)
2.2 容器生命周期管理
1)创建并运行容器:podman run [选项] <镜像名>
| 选项 | 助记 | 功能描述 |
|---|---|---|
-d |
detach | 后台运行容器。容器启动后,终端会立即返回,并只显示容器ID。不会阻塞当前命令行窗口。 |
-it |
-i (--interactive) + -t (--tty) | 交互式运行容器并分配一个伪终端。通常用于启动需要直接交互的容器(如进入Shell)。 |
--name |
name |
为容器指定一个自定义名称,而不是使用系统生成的随机名称。便于后续管理(如启动、停止)。 |
-p |
port | 端口映射。将主机的端口映射到容器的端口,使得外部可以通过主机IP访问容器内的服务。 |
-v |
volume | 挂载数据卷。将主机上的一个目录或文件挂载到容器中,实现数据持久化或宿主机与容器间共享文件。 |
--rm |
remove | 容器退出后自动删除。适用于临时测试任务,容器停止后会自动清理,避免积累大量停止的容器。 |
podman run -d --name my_web nginx:alpine (后台运行一个名为 my_web 的 Nginx 容器)
podman run -p 8080:80 nginx (运行Nginx并将容器80端口映射到主机8080端口)
podman run -it --rm ubuntu bash (交互式运行一个临时Ubuntu容器,退出即删除)
2)启动容器:podman start <容器名或ID>
3)停止容器:podman stop <容器名或ID>
4)重启容器:podman restart <容器名或ID>
5)暂停/恢复容器:podman pause / podman unpause <容器名或ID>
6)删除容器:podman rm <容器名或ID>,使用 -f 选项强制删除运行中的容器。
podman rm -f my_web
注:删除前,必须先停止容器。
2.3 查看与监控
1)列出容器:
podman ps # 查看运行中的容器
podman ps -a # 查看所有容器,包括已停止的
2)查看日志:podman logs <容器名或ID>,使用 -f 选项实时跟踪日志输出。
podman logs -f my_web
3)查看详情:podman inspect <容器名或ID> (以JSON格式显示容器或镜像的详细配置信息)
4)查看资源统计:podman stats (实时显示所有容器的CPU、内存等资源使用情况)
5)查看进程:podman top <容器名或ID> (查看容器内运行的进程)
6)执行命令:podman exec [选项] <容器名或ID> <命令>,常用 -it 选项进入容器交互界面。
podman exec -it my_web /bin/sh
2.4 数据管理
1)创建卷:podman volume create <卷名> (创建命名的持久化数据卷)
2)列出卷:podman volume ls
3)使用卷:在 podman run 命令中使用 -v 选项
podman run -v <卷名>:<容器内路径> ... (使用命名卷)
podman run -v <主机路径>:<容器内路径> ... (挂载主机目录)
2.5 系统与信息
查看信息:podman info (显示系统、存储、运行时等全面信息)
查看版本:podman version
2.6 登录镜像仓库
登录到镜像仓库之后,可以进行拉取、上传等操作
podman login -u <用户名> --password <服务器地址>
# 输入密码,回车
# 或者
echo "<密码>" | podman login -u <用户名> --password-stdin <服务器地址> # 推荐
注:不指定 <服务器地址>时,Podman 会默认尝试登录 Docker Hub (docker.io)。
不要使用以下方式登录,因为密码会明文保存在 shell 历史记录中。
podman login -u <用户名> --password <密码> <服务器地址>
2.7 退出镜像仓库
podman logout # 默认 Docker Hub (docker.io)
podman logout <服务器地址>
三、把容器做成服务的形式
普通用户可以使用 systemctl 命令来启动、停止、重启服务等,通过创建 systemd 单元配置 rootless 容器,可将容器作为常规的系统服务进行管理。
1)在主机上创建数据目录并更改权限
创建要映射到容器内的主机目录,并确保运行容器的用户有权访问它。
# 示例
mkdir /host/data
# 改权限为将要运行容器的用户
chown testuser:testuser /opt/cloud
2)登录管理容器的用户账户
如果尚未创建用户,可先创建:sudo useradd testuser。然后必须通过SSH登录该用户:
ssh testuser@localhost
注意:Podman 在 rootless(非root)模式下,依赖每个用户独立的后台进程和通信套接字,这些都由用户级的 systemd --user 管理。
SSH 登录会自动创建完整的用户会话并启动 systemd --user,所以我们通过此方式登录后操作。而 sudo 或 su 只是切换了权限,没有创建完整的用户会话,导致找不到后台进程和套接字,因此不能使用。
3)创建并运行测试容器,验证配置
这一步的目的是作为一个配置模板,验证所有参数是否正确后再生成服务文件。完成后停止测试容器,为其生成服务文件做准备。
podman run -d \
--name myapp \ # 容器名
-v /host/data:/container/data:Z \ # 卷映射路径
<仓库位置>/<镜像名称>:<标签> # 使用实际镜像名
# 完成后停止测试容器,锁定其配置
podman stop myapp
其它参数可以根据需要添加。
注:Z 选项是为了自动设置目录的 SELinux 上下文,当然也可以自己手动设置为container_file_t。
更多有关 SELinux 的内容请查看以下文章:
【Linux】权限管理详解(三):SELinux安全性管理 | Redhat_selinux权限-CSDN博客
4)生成Systemd服务文件
基于已停止的测试容器生成服务文件。--new参数确保服务每次启动时都创建新容器,而不是重启旧容器。
# Rootless (用户级):
mkdir -p ~/.config/systemd/user/
cd ~/.config/systemd/user/
podman generate systemd --name myapp --new --files
# 删除测试容器
podman rm -f myapp
补充:
# Rootful:
cd /etc/systemd/system/
sudo podman generate systemd --name myapp --new --files
5)重新加载并启动Systemd服务
systemctl --user daemon-reload
systemctl --user enable --now container-myapp.service
6)配置为系统引导时启动
启用 linger 使用户服务在系统启动时自动运行。
loginctl enable-linger
# 恢复
loginctl disable-linger
除了上述介绍的方式外,还可以手动创建 Systemd 服务文件完成,此处不多介绍。
有关容器的更多内容将在【Docker】专栏进行介绍。
如有问题或建议,欢迎在评论区中留言~
更多推荐


所有评论(0)